Stranger things have happened at sea. Let's say you're converting some code that returned a List<T> to use Options because sometimes nulls were getting added and you're fed up of the NPEs. As a final point a List<Option<T>> might not be what you want but it's probably a pretty handy intermediate step in cleaning that kind of code up. As an extra, you could make a List implementation that overrides add, rejecting null, to help spot any that you didn't know about.
Can Java.next please not support null? Thanks. On Fri, Jul 6, 2012 at 8:12 AM, Dale Wijnand <[email protected]> wrote: > On the fly I can't think of a reason to return a List<Option<T>>, that's > just ridiculous. > > > On Friday, July 6, 2012 12:41:26 PM UTC+2, 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 <reinierz AT gmail (dot) >>> com>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/-/NR37xDf42BgJ<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 javaposse+unsubscribe@** >>>> googlegroups.com <javaposse%[email protected]>. >>>> For more options, visit this group at http://groups.google.com/** >>>> group/javaposse?hl=en <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/-/alKPZIyxOZUJ. > > 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 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.
