I'd use annotations for this. If you give me an Option<T>, that's not TOO 
bad, but if you give me i.e. a List<Option<T>>, you're pretty much forcing 
me to jump through awkward hoops.

On Tuesday, July 3, 2012 10:27:57 AM UTC+2, Dale Wijnand wrote:
>
> 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 view this discussion on the web visit 
https://groups.google.com/d/msg/javaposse/-/HCKCewFDJ3kJ.
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