Nope, my goal is to make intent clearer in the type signature.

However I'm interested to know what candidates would you suggest to improve 
developer experience?

On Friday, July 6, 2012 1:08:02 PM UTC+2, KWright wrote:
>
> For example, converting said list to a list of strings:
>
> myList map { _ map {_.toString} getOrElse "(null)" }
>
>
> compared to a version using nulls
>
> myList map { x => if (null == x) x else x.toString }
>
>
> or if you just want to drop all the Nones:
>
> myList.flatten
>
>
> same again, using nulls:
>
> myList filter { _ != null }
>
>
>
> There's no hoopiness from using Options here, not so long as you have 
> lambdas.  Now compare a lambda-free version.  I'm using Google guava here 
> to maintain immutability characteristics and so keep it a like-for-like 
> comparison.  Also using both the enhanced-for notation and the tertiary 
> operator to reduce the boilerplate as much as possible:
>
> ImmutableList.Builder<String> out = ImmutableList.builder<String>
> for(T x : myList) {
>   out.add((null==x) ? "null" : x.toString)
> }
> out.build()
>
>
> Conclusion:  If your goal is to avoid jumping through hoops, then picking 
> on Option isn't exactly fertile ground.  There are *much* better candidates 
> for improving the developer experience.
>
>
> On 6 July 2012 11:41, Reinier Zwitserloot wrote:
>
>> 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 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-**li*
>>>>> *braries.googlecode.com/git-**his**tory/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-**libra**
>>>>>> ries.googlecode.com/git-**histor**y/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/-/I7RrAp2aXQoJ.
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