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.