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