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

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.
>  
> 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/-/JKzmRfsviU0J.
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