@jxtps Thank you for writing up your proposal. I’ll start with answering a few individual points that arose in the discussion.
This is normal. It is analogous to the fact that
Option(null) != Some(null), but
Option(1) == Some(1).
USome(null) == null. In general,
USome(x) == x for all
No you can’t do any better than unboxed-option, because the implementation of unboxed-option is already basically what an opaque type would provide. It’s just very hard to correctly implement without opaque types baked into the language, but in this specific case it can be done.
I see this thread as an opportunity to remind people of one very important thing:
Option is not a better way to deal with
null! It is a better way to deal with optional values.
null itself is a poor way to deal with optional values. It is not type parametric, as you cannot represent an optional value of a type that can itself hold
null. I have said that countless times, and for the most part I have stopped trying to explain this. But this thread might be the first time someone actually suggests this in a post including “SIP” in the title, so maybe it’s worth trying one more time.
For that reason, aliasing
A | Null is a terrible idea. It’s a very common idea, unfortunately. Even Martin wanted to do that. The big problem if you do that is that it will be easier to write
Option[A], so people will write
A | Null is not type parametric, and that will cause countless obscure bugs. We’ll have regressed to Java-like unsafety about
null, perhaps even worse than Java because of the false sense of security in doing so. If at all,
A? should desugar to
Option boxes, but at least it is type parametric.
And that brings me to the original proposal.
This kind of “if it has this type shape, do that, otherwise do that” has no precedent in Scala, and it would be dangerous. Because if I have an
A and I use this operator, I don’t really know whether
null is supposed to be considered as “empty” or as "valid value that happens to be
null". This operator would end up turning too many
None. It’s bad enough that
Option(x) is named as it is (it should be
Option.fromNullable(x) or something like that), but giving it a short alias like that is going to make it be used even more. But this constructor is completely overused already. How many have I seen people writing
Option(x) instead of
So, at the very least we should scrap everything that implicitly converts from
Option[A] in the proposal. If we do that we’re left basically with
a: String? as a parameter is something that
- at call site, can be given a
String, or can be not given at all.
- at call site it would also make sense to allow passing
x: _? when
x is an
Option[String], which corresponds to
x: _* for varargs when
x is a
- at definition site, inside a method,
a is an
- an “Elvis” operator
x?.f, which is actually nothing more than syntactic sugar for
When you look at it that way, the two main bullets are really separate proposals. The second one probably wouldn’t hold its ground, because it is redundant wrt. for comprehensions, and does not provide a solution for the
flatMap case. The first bullet is defensible.