Some notes on Elvis and Other Null-Safe Operators
Mark Mahieu
markmahieu at googlemail.com
Mon Apr 13 05:01:53 PDT 2009
Below are a few observations I compiled while building and testing
the prototype for Elvis and friends, in case they're of interest.
They are in note form and fairly random order, so please shout if
anything isn't clear.
Mark
--------
Elvis operator can be approximated as a library method:
static <T> T elvis(T t1, T t2) { return t1 != null ? t1 : t2; }
In a core-libs round table recording (at http://mail.openjdk.java.net/
pipermail/core-libs-dev/2009-April/001406.html) the possibility of
adding core library methods for common null-handling tasks is
mentioned, such as throwing a standard exception if a supplied
argument is null (presumably similar to methods in
com.google.common.base.Preconditions). Is it reasonable to implement
the Elvis operator as a language change but other null-handling
facilities as library changes?
Cannot use null-safe method invocation as a statement:
stringBuilder?.append(“some text”); // compiler error
which is legal in Groovy and Fan, even for methods with void (or
Void) result, eg. given:
Map<Key, Runnable> map = ...
some legal Groovy code:
map?.get(someKey)?.run();
and the equivalent with this proposal:
Runnable r = map?.get(someKey);
if (r != null)
r.run();
However, this is accepted:
map?.get(someKey).run();
yet is almost certainly an error. Should there at least be a
warning in this case?
Groovy will also allow the following:
someObject?.someField = someValue
which does nothing at runtime if someObject is null. Fan and
this proposal both reject it.
As discussed on coin-dev, this isn't legal as containsKey() returns a
primitive type:
if (!map?.containsKey(key) ?: false) ... // compiler error
Would it be clear to someone reading the code that these two
statements are equivalent?
if (map?.get(key) == null) ...
if (map == null || map.get(key) == null) ...
Given:
101: Map<Foo, Bar> map = ..
102: Bar bar = map?.get(someFoo);
103: ...
204: bar.execute();
where the programmer has forgotten to protect the bar.execute()
call (or was unaware of the need, perhaps in a different method), the
NPE will point at line 204, even if the root cause was 'map' being
null. Without use of ?. It would point at line 102 or 204 depending
on which variable was null.
Groovy has supported Elvis since v1.5 (Dec 2007), other operators for
longer. Few Google Code Search results for the former, plenty for
the latter (but a large percentage cannot be adapted to use
equivalents from this proposal because the method call results in a
primitive type, or is used as a statement).
Fan has only had Elvis etc since a July 2008 build (1.0.29).
C# has had Elvis-equivalent '??' operator since v2.0.
More information about the coin-dev
mailing list