Some notes on Elvis and Other Null-Safe Operators
Reinier Zwitserloot
reinier at zwitserloot.com
Mon May 18 23:06:36 PDT 2009
I agree with you that this 'meh, let's see what happens' attitude
doesn't exactly sound kosher, but them's the breaks. Presuming, of
course, that you agree that there's a -big- difference for very small
utility classes and methods being in java core, and being in a third
party library. That, or we make guesses about a Utils.elvis() method's
popularity, which seems similarly objectionable.
But, back on the topic of the elvis operator as a library for a
moment: Even if some form of it would be added to the core libraries,
what would that look like? All I can come up with:
with the actual null checking operators:
public void test() {
Integer x = foo?.bar()?.baz();
return x ?: 0;
}
library attempt:
public void test() {
Integer x = Utils.ifNotNull(new IfNotNullBlock<Integer>() {
public void run() {
return foo.bar().baz();
}
});
return Utils.elvis(x, 0);
}
contrast this to how I'd do this now, without either a library or an
operator:
public void test() {
Integer x = barBaz(foo);
return x != null ? x : 0;
}
private void fooBarBaz(Foo foo) {
if ( foo == null ) return null;
Bar bar = foo.bar();
if ( bar == null ) return null;
return bar.baz();
}
The actual elvis operator could be a library, sure, but a null-safe
dereferencing operator clearly couldn't be, unless I'm missing
something. Because elvis looks acceptable without a library, just
written out with a ternary operator, and because elvis does librarify
(coining words here!) somewhat nicely, The amount of pain/boilerplate
you can eliminate with the null safe derefencing operator (?.) is
considerably bigger than elvis. Though, from anecdotal evidence and
Ruslan's work, ?: would be useful more often. Personally, I can't
recall even a single instance of having to write out a chain of method
calls that all need to be null-safed out (though I admit I tend to
avoid nulls like the plague in the first place).
The value of a language change for coin is something along the lines
of (boilerplate eliminated * frequency of use case) / (negative impact
on the language). The negative impact part is equal, as far as I can
tell, so it boils down to boilerplate*frequency. I'm not sure which
one is the winner there - elvis avoids a little boilerplate a lot of
the time, and null-safe dereference avoids a lot of boilerplate, only
a few times. Given that introducing related changes in batch form has
its own advantages, I'm somewhat confused as to why this proposal
isn't a both or neither kind of deal: Whats the thinking behind
introducing ?: but not ?. and, possibly, ?[], though where do you draw
the line? Technically we'd need a synchronized ( foo? ), a throw foo?,
and a for ( x : foo? ) as well, if you want to cover all the
situations that can result in NPEs!).
FWIW, the for ( x : foo? ) thing seems more useful to me than ?[],
because arrays are a niche device compared to the Collections API, and
the amount of boilerplate involved is bigger (either a lengthy foo ?:
Collections.emptyList() - which adds an import dependency, or a whole
new nesting level by prefixing the entire for loop with an if ( foo !=
null ) {}, compared to just foo != null ? foo[x] : null).
--Reinier Zwitserloot
On May 19, 2009, at 07:34, Mark Mahieu wrote:
>
> On 19 May 2009, at 05:13, Reinier Zwitserloot wrote:
>>
>> So, is the elvis operator a good idea? Probably - I'm mostly
>> agnostic*, but if I had to make the final call, sure, why not.
>
> Can't beat a well-reasoned argument like that ;)
>
>
>> However, we clearly cannot say that 'the library path doesn't work' -
>> because we haven't tested the library path yet. Toss it into
>> java.lang.Something, and if people then still won't go for it, THEN
>> we
>> know it won't fly as a library**.
>
> Is that language design by Coin-toss?
>
>
> Mark
More information about the coin-dev
mailing list