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.
 
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 <[email protected]> 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/-/6ExMALJnkJcJ.
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