Loose ends: Optional
forax at univ-mlv.fr
Mon Jun 10 03:01:13 PDT 2013
On 06/07/2013 09:47 PM, Brian Goetz wrote:
>> I think we have clearly two options, and I'm fine with both of them:
>> Option A: We want to add map/flatMap.
>> In that case, we also need to add a way to do the conversion back and
>> fore to null (orNull() and fromNullable()).
> I see your point, but I don't think this necessarily follows (though
> it is certainly something to discuss.)
> Neither Guava, Fugue, nor j.u.Optional allow Optional to hold a null.
Holding null or not is an implementation detail. Providing conversion
from/to null is not.
> The fromNullable proposal is merely a convenience method; anyone can
> write it as an expression (o == null ? O.empty() : O.of(o)) or as a
> static method (MyFoo.ofNullable). So it is by no means *necessary*.
We are talking about convenience methods since the beginning of this
thread, no ?
> Now, the same can be superficially said of map/flatMap -- people can
> easily write these themselves too -- but there is a key difference;
With the method map you propose, instead of
(foo() == null ? O.empty() : O.of(o))
you can write
O.of("unused").map(unused -> foo())
which is ugly but more fluent.
So fluency is nice but it should never trump the semantics.
> People want flatMap not because it offers functionality people can't
> write for themselves, but that they can't otherwise do it fluently at
> the end of a chain.
yes, the question is more. Why do they need flatMap ?
If they need flatMap to do optional?.foo()?.bar(), then Optional should
be a boxing of null.
> But at the other end of the chain, whether the factory method is
> "Optional.ofNullable" or "MyFoo.ofNullable", there is effectively no
> difference, so these are different cases.
From the fluency point of view, I agree. But I care more about the
semantics, providing the proper abstraction is more important for me.
> So, I would amend your statement to: if we add map/flatMap, we then
> have to ask the question of whether we should also add ofNullable.
Yes, map can take a method that return null and flatMap can not be used
with a method that returns null instead of Optional.
That's the issue.
As I said, the issue is not exactly if we add map/flatMap, but more how
we deal with null in map().
> I find this method also in the category of "mostly harmless", but left
> it out of the initial proposal in spirit of minimality; limiting the
> set of proposed methods to those that where having them in the JDK
> type adds the most value.
> If the EG will only take filter/map/flatMap if we add ofNullable, I'm
> OK with that. (On the other hand, if where you are going is "if we
> add X we have to add Y, and then we have to add Z, and X+Y+Z is too
> much, so let's do none of them", then I'm not so OK.)
that's not what I said.
>> Note that the original code proposed by Brian below already does a
> > null check in map().
> There are two null checks. First is a check if the mapper function
> itself is null -- since a null function is clearly a bug. I assume
> you are talking of the other, which is the "treat null return as
> nothing there" interpretation of the mapper result. There's a valid
> choice here -- NPE vs interpret as empty. The latter is consistent
> with the other methods we've added to Map, such as computeIfAbsent.
> But we can also discuss throwing NPE here.
but in all Stream methods that returns an Optional like
Stream.findFirst(), null is not interpreted as empty,
That's why I said that we have two choices, either we consider that null
is empty, and Optional.of() should work that way or
we consider that we can never receive null (so throws NPE) and we need
to provide ofNullable otherwise people
will not be able to use flatMap.
The current proposed semantics is "sometimes null is empty, sometimes
not", which is ugly.
More information about the lambda-libs-spec-observers