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



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

Reply via email to