I've found it very useful to design my API, making the intent evident
from the type signature ("this method might not have a return value
for you").

Unfortunately it's a bit verbose and of limited use in Java than in Scala
but it still beats ambiguity and having to resort to reading the Javadoc
(or, even worst, making assumptions)..

Dale

On 2 July 2012 23:34, Reinier Zwitserloot <[email protected]> wrote:

> On Tuesday, June 12, 2012 8:52:30 AM UTC+2, Dale Wijnand wrote:
>>
>> The class Tobias is talking about (which I can't believe no one mentioned
>> yet, thanks Tobias) is Optional: http://docs.guava-**
>> libraries.googlecode.com/git-**history/v12.0/javadoc/com/**
>> google/common/base/Optional.**html<http://docs.guava-libraries.googlecode.com/git-history/v12.0/javadoc/com/google/common/base/Optional.html>
>
>
>
> Nobody mentioned it, probably because it's frankly unusable in java. As
> has been covered before, if you use Option, you _NEED_ closures all over
> the place; there needs to be a way to map your type for ANY operation that
> runs on a collection of said type, such that you can easily pass a
> collection of Option<type> along with a mapping.
>
>
>>
>> I also like the use of JSR 305 annotations, which I think work well for
>> parameters, while using Optional for return types when not returning a
>> value is an expected result (as opposed to an exception case, in which case
>> I prefer to design the API to throw an exception).
>>
>> Dale
>>
>> On Monday, June 11, 2012 10:12:18 PM UTC+2, Tobias Neef wrote:
>>>
>>> Some of you may be interested that Google Guava also contains a Type to
>>> represent optional values http://docs.guava-**
>>> libraries.googlecode.com/git-**history/v12.0/javadoc/index.**html<http://docs.guava-libraries.googlecode.com/git-history/v12.0/javadoc/index.html>.
>>> I use this approach a lot in the most recent java projects I have done. In
>>> my own code this is a nice thing, but in contrast to the scala word we have
>>> a lot of places in java which do not follow this pattern. As a result we
>>> still have issues with NPEs from time to time.
>>>
>>> In the most recent version it is also possible to apply a function on
>>> the Optional object using the transform function which is similar to the
>>> scala 'map' behavior which was described by Dick. Because the
>>> guava library is already used in a lot of places, some Java projects will
>>> maybe start using this way of dealing with optional values. Another
>>> advantage of guava is, that it uses the JSR 305 annotations for static type
>>> checking which also helps to avoid nulls. This is especially helpful for
>>> methods those methods of the Guava Collections or the Optional type which
>>> do not allow null parameters.
>>>
>>> On Tuesday, June 5, 2012 1:19:52 PM UTC+2, KWright wrote:
>>>>
>>>>
>>>>
>>>> On 5 June 2012 11:05, Reinier Zwitserloot wrote:
>>>>
>>>>> On Monday, June 4, 2012 5:09:43 PM UTC+2, KWright wrote:
>>>>>>
>>>>>>
>>>>>> This now has alarm bells going off in my head.  These (as described)
>>>>>> would only make sense if specified at both declaration AND use site, 
>>>>>> that's
>>>>>> an awful lot of boilerplate and ceremony to be added!  We already tried 
>>>>>> the
>>>>>> same thing with checked exceptions, and you know how well that 
>>>>>> succeeded...
>>>>>>
>>>>>
>>>>> Yes, you need to specify both at declaration and use. Like _ANY_ type.
>>>>> Why does that have alarm bells going off in your head?
>>>>>
>>>>> String x = "Hello"; //site 1
>>>>> System.out.println(x);
>>>>>
>>>>> public void println(String in) { ... } //site 2
>>>>>
>>>>> That's perfectly normal, no need for alarm bells.
>>>>>
>>>>>
>>>> Not quite.  In addition to the regular type system, we also have the
>>>> shadow type systems of annotations and checked exceptions.  This would be a
>>>> third shadow system and it *would* add complexity.
>>>>
>>>> I suspect that Nullity in this form could be internally implemented
>>>> through annotations to minimise the effort required, yet it would have to
>>>> follow different rules in the presence of subtyping (more later).  In
>>>> practice, it would feel a lot more like generics - optional, erased, yet
>>>> still part of the type system.
>>>>
>>>> Nullity is close to variance in this regard.  With use-site (Java) or
>>>> declaration-site(C#, Scala) approaches both being possible.  If I could
>>>> statically type Map<K!, V!> when *defining* the class, then using a
>>>> guava-esque factory we might have:
>>>>
>>>> public static final Map<String, Integer> example = Map.of("a", 1, "c",
>>>> 2)
>>>>
>>>>
>>>> declaration-site nullity.  No extra ceremony or boilerplate in the
>>>> client code :)
>>>>
>>>>
>>>>
>>>>>
>>>>>> Then there's the issue of subtyping and the LSP to consider.
>>>>>>
>>>>>
>>>>> No, the 4-nulls thing actually solves this. Technically, you could
>>>>> treat [dunno-null] as "? extends String! super String?" if you really
>>>>> wanted to, but you can simplify matters considerably by taking nullity out
>>>>> of the type inheritance system. String is a type, and where inheritance is
>>>>> concerned, String is just String, and the nullity of it does not enter 
>>>>> into
>>>>> the equation whatsoever; String, String!, String?, String[raw], it's all
>>>>> the same to the type system. As in, == equals - the exact same. If there's
>>>>> a mismatch between a type's nullity state and the operation you do on it,
>>>>> then the compiler will emit an error (you're treating a could-be-null as 
>>>>> if
>>>>> it's never-null, or you're passing a could-be-null to something that wants
>>>>> a never-null) or a warning (you're doing null-checks on a never-null). 
>>>>> This
>>>>> errors-and-warnings system is like a compiler plugin, it has no actual
>>>>> effect on the meaning of any of the code nor of how any of the code is
>>>>> compiled, the ONLY thing that it could possibly cause is errors and
>>>>> warnings. It's analogous to @Override in that sense. Just compiler-checked
>>>>> documentation is all.
>>>>>
>>>>> If you want to be technical about it, nullity is its own tiny little
>>>>> non-expandable strictly and statically defined hardcoded type system. The
>>>>> upshot is that it's all very easy to reason about and there's no risk of
>>>>> conflicting with existing specs. For example, you cannot write both:
>>>>>
>>>>> public static void test1(String? foo) {}
>>>>>
>>>>> public static void test1(String! foo) {}
>>>>>
>>>>> in the same file, but that would have been possible if these were
>>>>> actually different types.
>>>>>
>>>>
>>>> Here's a thought experiment, I have:
>>>>
>>>> public class Foo { ... }
>>>> public class Bar extends Foo { ... }
>>>> public void doSomething(List<? super Bar!> xs)
>>>>
>>>>
>>>> What would be a valid argument to doSomething?
>>>>
>>>> List<Bar!>
>>>> List<Bar>
>>>> List<Foo!>
>>>> List<Foo>
>>>>
>>>>
>>>> This is definitely something outside the current spec, so adding it
>>>> would be a mammoth task - possibly the same order of magnitude as both
>>>> generics and annotations.
>>>>
>>>>
>>>>
>>>>>
>>>>>
>>>>>>   It's easy enough to say that String is a subtype of both String!
>>>>>> and String?, but it massively changes the Java spec (which only allows
>>>>>> subtyping through inheritance).  It looks like we'd be in a similar
>>>>>> position to having Array[Object] being a supertype of Array[T], and the
>>>>>> problems that caused.  Then you still have the midas problem if you need 
>>>>>> to
>>>>>> pass a String where a String! is demanded.  And how does it work inside
>>>>>> collections and generics (especially wildcarded ones)? and through
>>>>>> reflection?
>>>>>>
>>>>>>
>>>>> See above - no changes needed whatsoever. There is also no midas
>>>>> problem here; just because I use this equivalent of Option somewhere does
>>>>> NOT mean my code is going to end up with every type in every parameter
>>>>> replaced with Option<T> everywhere! Generalized APIs such as List will 
>>>>> most
>>>>> likely roll with dunno-Ts everywhere but this is completely transparent to
>>>>> ALL nullities: You can pass never-nulls, could-be-nulls, and dunno-nulls 
>>>>> to
>>>>> such an API and it would all work. Maybe you don't understand the midas
>>>>> problem? With Option, then I start having List<Option<X>> everywhere,
>>>>> severely complicating my API documentation and requiring me to also start
>>>>> using option. The entire _point_ of the 4-nullity concept is that null
>>>>> safety is transparent yet compile-time checked. Contrast to Option, which
>>>>> is compile-time checked but not transparent, and java's system, which is
>>>>> transparent but not compile-time checked.
>>>>>
>>>>>
>>>>>
>>>> public String! turtleA() { return turtleB(); }
>>>> public String turtleB() { return turtleC(); }
>>>> public String turtleC() { return ...; }
>>>> ... continue until you run out of turtles ...
>>>>
>>>>
>>>> Every method below the top one now has to be changed to return a
>>>> String! (unless you provide some form of nullity cast).  Is this not the
>>>> essence of the midas problem?
>>>>
>>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>> I have no solution for this dilemma, other than introducing an IDE
>>>>>>> which exceeds the ascii character set for symbols, and which introduces
>>>>>>> certain keyboard shortcuts to change nullity. But that's an entirely
>>>>>>> different can of worms.
>>>>>>>
>>>>>>>
>>>>>> Not just the IDE.  You have javadoc, static analysis tools, code
>>>>>> coverage, etc. etc.
>>>>>>
>>>>>
>>>>> Nope, those can just use the long-form ASCII symbol that is in the
>>>>> actual source file. It's fine in all such tools, but where it gets real
>>>>> tedious is in day-to-day edit work, but if your IDE can let you enter the
>>>>> appropriate nullity state very easily, and render it in an unobtrusive
>>>>> manner, you've gotten your 90% in and it's fine then.
>>>>>
>>>>>
>>>>>>
>>>>>> It's a bold solution, to be sure.  But the work and complexity
>>>>>> required to retrofit it look more complicated than Option[T] at this 
>>>>>> stage.
>>>>>>  That's before you even consider composability.
>>>>>>
>>>>>
>>>>>
>>>>> Hah, just... no. It is not possible to retrofit java to Option<T>
>>>>> because that is not transparent; APIs are set in stone, you can't change
>>>>> them. 4-nullities is transparent which means that's actually an option, al
>>>>> though it is very complex.
>>>>>
>>>>> Sure.  Retrofitting is *always* harder than getting a clean design in
>>>> the first place.  This is why C# forked the collections when they added
>>>> generics.  I also consider Scala's collections to be a similar fork - not
>>>> just adding option awareness, but also immutability at the root of the
>>>> hierarchy and all sorts of monadic goodness.  Other such examples are
>>>> Google Guava and the totallylazy library.  This can happen at the library
>>>> level without requiring sweeping changes to the type system in the language
>>>> spec.
>>>>
>>>>  --
> You received this message because you are subscribed to the Google Groups
> "Java Posse" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/javaposse/-/NR37xDf42BgJ.
>
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups "Java 
Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to