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.
