Skip to content
Print

Implementing Groovy’s Elvis Operator in Scala

7
Jul
2008

Groovy has an interesting shortening of the ternary operator that it rather fancifully titles “the Elvis Operator“.  This operator is hardly unique to Groovy – C# has had it since 2.0 in the form of the Null Coalescing Operator – but that doesn’t mean that it is not a language feature worth learning from.  Surprisingly (for a C-derivative language), Scala entirely lacks any sort of ternary operator.  However, the language syntax is more than flexible enough to implement something similar without ever having to dip into the compiler.

But before we go there, it is worth examining what this operator does and how it works in languages which already have it.  In essence, it is just a bit of syntax sugar, allowing you to easily check if a value is null and provide a value in the case that it is.  For example:

firstName = "Daniel"
lastName = null
 
println firstName ?: "Chris"
println lastName ?: "Spiewak"

This profound snippet really demonstrates about all there is to the Elvis operator.  The result is as follows:

Daniel
Spiewak

Not terribly exciting.  Essentially, what we have is a binary operator which evaluates the left expression and tests to see if it is null.  In the case of firstName, this is false, so the right expression (in this case, "Chris") is never evaluated.  However, lastName is null, which means that we have to evaluate the right expression and return its value, rather than null.  It’s all just so much syntax sugar that can be expressed equivalently in any language with a conditional operator (in this case, Java):

String firstName = "Daniel";
String lastName = null;
 
System.out.println((firstName == null) ? "Chris" : firstName);
System.out.println((lastName == null) ? "Spiewak" : lastName);

A bit verbose, don’t you think?  Of course, this isn’t really a fair comparison, since Groovy is a far more concise language than Java.  Let’s see how the above would render in a real man’s language like Scala:

val firstName = "Daniel"
val lastName: String = null
 
println(if (firstName == null) "Chris" else firstName)
println(if (lastName == null) "Spiewak" else lastName)

Better, but still a little clumsy.  The truth of the matter is that we’re forced to do this sort of null checking all the time (well, maybe a little less in Scala) and the constructs for doing so are woefully inadequate.  Thus, the motivation for the Elvis operator.

Getting Things Started

Like all good programmers should, we’re going to start with a runnable specification for every behavior desired from the operator.  I’ve written before about the excellent Specs framework, so that’s what we’ll use:

"elvis operator" should {
  "use predicate when not null" in {
    "success" ?: "failure" mustEqual "success"
  }
 
  "use alternative when null" in {
    val test: String = null
    test ?: "success" mustEqual "success"
  }
 
  "type correctly" in {		// if it compiles, then we're fine
    val str: String = "success" ?: "failure"
    val i: Int = 123 ?: 321
 
    str mustEqual "success"
    i mustEqual 123
  }
 
  "infer join of types" in {    // must compile
    val res: CharSequence = "success" ?: new java.lang.StringBuilder("failure")	
    res mustEqual "success"
  }
 
  "only eval alternative when null" in {
    var a = "success"
    def alt = {
      a = "failure"
      a
    }
 
    "non-null" ?: alt
    a mustEqual "success"
  }
}

Fairly straightforward stuff.  I imagine that this specification for the operator is a bit more involved than the one used in the Groovy compiler, due to the fact that Scala is a statically typed language and thus requires a bit more effort to ensure that everything is working properly.  From this specification, we can infer three core properties of the operator:

  1. Basic behavior when null/not-null
  2. The result type should be the unification of the static types of the left and right operands
  3. The right operand should only be evaluated when the left is null

The first property is fairly easy to understand; it is intuitive in the definition of the operator.  All this means is that the value of the operator expression is dependent on the value of the left operand.  When not null, the expression value is equal to the value of the left operand.  If the left operand is null, then the expression is valued equivalent to the right operand.  This is just formally expressing what we spent the first section of the article describing.

Ignoring the second and third properties, we can actually attempt an implementation.  For the moment, we will just assume that the left and right operands must be of exactly the same type, otherwise the operator will be inapplicable.  So, without further ado, implementation enters stage right:

implicit def elvisOperator[T](alt: T) = new {
  def ?:(pred: T) = if (pred == null) alt else pred
}

Notice the use of the anonymous inner class to carry the actual operator?  This is a fairly common trick in Scala to avoid the definition of a full-blown class just for the sake of adding a method to an existing type.  To break down what’s going on here, we have defined an implicit type conversion from any type T to our anonymous inner class.  This conversion will be inserted by the compiler whenever we invoke the ?: operator on an expression.

Sharp-eyed developers will notice something a little odd about the way this code is structured.  In fact, if you look closely, it seems that we evaluate the right operand and use its value if non-null (otherwise left), which is exactly the opposite of what our specification defines.  For a normal operator, this observation would be quite correct.  However, Scala defines the associatively of operators based on the trailing symbol.  In this case, because our trailing symbol is a colon (:), the operator itself will be right-associative.  Thus, the following expression:

check ?: alternate

…is transformed by the compiler into the following:

alternate.?:(check)

This is how right-associative operators function, by performing method calls on the right operand.  Thus, we need to define our implicit conversion such that the ?: method will be defined for the right operand, taking the left operand as a parameter.  We’ll see a bit later on how this can cause trouble, but for now, let’s continue with the specification.

A Little Type Theory

The second property is a little tougher.  Type unification is one of those pesky issues that plague statically typed languages and are simply irrelevant in those with dynamic type systems.  The issue arises from the following question: what happens if the left and right operands are of different types?  In Groovy, this is a non-issue because the value of the expression is simply dynamically typed according to the runtime type of the operand which is chosen.  However, Scala requires static type information, which means that we need to ensure that the static type of the expression is sound for either the left or the right operand (since Scala does not have non-nullable types).  The best way to do this is to compute the least upper bound of the two types, an operation which is also known as minimal unification.  Consider the following hierarchy:

image

Now imagine that the left operand is of static type Apple, while the right operand is of static type Pear.  We need to find a static type which is safe for both of these.  Intuitively, this type would be Fruit, since it is a common superclass of both Apple and Pear.  Regardless of which expression is chosen at runtime, we will be able to polymorphically treat the value as a value of type Fruit.  The intuition in this case is quite correct.  In fact, it actually has a rigorous mathematical proof…which I won’t go into.  (queue sighs of relief)

One additional example should serve to really drive the point home.  Consider the scenario where the left operand has type Vegitable and the right operand has type Apple.  This is a bit trickier, but it recursively boils down to the same case.  The only common superclass between these two types is Object, due to the fact that the hierarchies are disjoint.

This operation is fairly easy to perform by hand given the full type hierarchy.  For that matter, it isn’t very difficult to write an algorithm which can efficiently compute the minimal unification of two types.  Unfortunately, we don’t have that luxury here.  We cannot simply write code which is executed at compile time to determine type information, we must make use of the existing Scala type system in order to “trick” the compiler into inferring things for us.  We do this by making use of lower-bounds on type parameters.  With this in mind, we can (finally) make a first attempt at a well-typed implementation of the operator:

implicit def elvisOperator[T](alt: T) = new {
  def ?:[A >: T](pred: A) = if (pred == null) alt else pred
}

The only thing we have changed is the type of the pred variable from T to a new type parameter, A.  This new type parameter is defined by the lower-bound T.  Translated into English, the type expression reads something like the following:

Accept parameter pred of some type A which is a super-type of T.

The real magic of the expression is that pred need not be exactly of type A; it could also be a subtype.  Thus, A is some generic supertype which encompasses both the types of the left and the right operands.

Fancy Parameter Types

This allows us to move onto the third property: only evaluate the right operand if the left is null.  This is the normal behavior for conditional expressions.  After all, you wouldn’t want your code performing an expensive operation (such as grabbing data from a server somewhere) just to throw away the result because a different branch of the conditional was chosen.  Actually, the bigger issue with ignoring this property (as we have done so far) is that the right operand may actually have side-effects.  Scala isn’t a pure functional language, so evaluating expressions that we don’t need (or worse, that the developer isn’t expecting) can have extremely dire consequences.

Unfortunately, at first glance, there doesn’t really seem to be a way to avoid this evaluation.  After all, we need to invoke the ?: method on something.  We could try using a left-associative operator instead (such as C#’s ?? operator), but even that wouldn’t fully solve the problem as we would still need to pass the right operand as a parameter.  In short, it seems like we’re stuck.

The good news is that Scala’s designers chose to adopt an age-old construct known as “pass-by-name parameters”.  This technique dates all the way back to ALGOL (possibly even further).  In fact, it’s so old and obscure that I’ve actually had professors tell me that it has been completely abandoned in favor of the more conventional pass-by-value (what Java, C#, Scala and most languages use) and pass-by-reference (which is available in C++).  Pass-by-name parameters are very much like normal parameters in that they are used to copy values from a calling scope into the method in question.  However, unlike normal parameters, they are evaluated on an as-needed basis.  This means that a pass-by-name parameter will only be evaluated if its value is required within the method called.  For example:

def doSomething(a: =>Int) = 1 + 2
def createInteger() = {
  println("Made integer")
  42
}
 
println("In the beginning...")
doSomething(createInteger())
println("...at the end")

Counter to our first intuition, this will print the following:

In the beginning...
...at the end

In other words, the createInteger method is never called!  This is because the value of the pass-by-name parameter in the doSomething method is never accessed, meaning that the value of the expression is not needed.  The a parameter is denoted pass-by-name by the => notation (just in case you were wondering).  We can apply this to our implementation by changing the parameter of the implicit conversion from pass-by-value to pass-by-name:

implicit def elvisOperator[T](alt: =>T) = new {
  def ?:[A >: T](pred: A) = if (pred == null) alt else pred
}

The language-level implementation of the if/else conditional expression will ensure that the alt parameter is only accessed iff the value of pred is null, meaning we have finally satisfied all three properties.  We can check this by compiling and running our specification from earlier:

Specification "TernarySpecs"
  elvis operator should
  + use predicate when not null
  + use alternative when null
  + type correctly
  + infer join of types
  + only eval alternative when null

Total for specification "TernarySpecs":
Finished in 0 second, 78 ms
5 examples, 6 assertions, 0 failure, 0 error

Conclusion

We now have a working implementation of Groovy’s Elvis operator within Scala and we never had to move beyond simple API design.  Truly, one of Scala’s greatest strengths is its ability to expression extremely complex constructs within the confines of the language.  This makes it uniquely well-suited to hosting internal domain-specific languages.  Using techniques similar to the ones I have outlined in this article, it is possible to define operations which would require compiler-level implementation in most languages.

The full source (such as it is) for the Elvis operator in Scala is available for download, along with a bonus implementation of C#’s ?? syntax (just in case you prefer it).  The implementation differs slightly due to the fact that ?? is a left-associative operator, but the single-use (unchained) semantics are identical.  Enjoy!

Comments

  1. “The Elvis operator” is equivalent to Option.getOrElse, so another solution is to implement an implicit conversion from T to Option[T] (and maybe pimp Option with an shorter operator for getOrElse).

    Jesper Nordenberg Monday, July 7, 2008 at 12:51 am
  2. The download link is not working. Thanks for an interesting article.

    Chris Monday, July 7, 2008 at 1:58 am
  3. This operator is very old. In Perl (and some other languages) you can just use the OR-Operator for this:

    $firstName = “Daniel”;
    $lastName = undef;

    print $firstName || “Chris”;
    print $lastName || “Spiewak”;

    Labaru Monday, July 7, 2008 at 2:19 am
  4. Hey Daniel,

    I get a 404 when trying to download the sources.

    David Linsin Monday, July 7, 2008 at 3:35 am
  5. Great article! Goes to show how flexible you can make the Scala syntax.

    The one thing I didn’t realize before is that implicit defs can have by-name arguments. That’s rad! As a test, I created a construct “onlyIf”, as in ‘print(“hello”) onlyIf false’ and it worked.

    One minor point of interest is that instead of ‘val lastName: String = null’ you could have written ‘val lastName = null:String’. (When it occurred to me I could write it the latter way, I immediately preferred it.) Another interesting use of giving an expression a type is triggering an implicit def. For example, if there was an implicit conversion from Int to FooName, you could write ‘print(12345:FooName)’. If there was another conversion from FooName to String, you could even write ‘val foo:String = 12345:FooName’ and cause both conversions to happen.

    DavidLG Monday, July 7, 2008 at 3:51 am
  6. Scala already has “the elvis operator”, it’s called getOrElse.

    Fredrik Monday, July 7, 2008 at 6:38 am
  7. /me slaps himself upside head

    Thanks for catching that, David! Just goes to show that I should *test* my download links before I post them. :-)

    Daniel Spiewak Monday, July 7, 2008 at 9:59 am
  8. JavaScript:

    alert(firstName || “Chris”)
    alert(lastName || “Spiewak”)

    Ted Henry Monday, July 7, 2008 at 10:01 am
  9. Interesting article, and tasty choice of use case to motivate an in-depth look at some Scala features.

    On the other hand, I have to say that the use of “pass-by-name” in this context looks like a brittle kluge when compared to hygienic macros. It doesn’t even seem to be the right name for what is apparently happening, since “createInteger()” is not a name; it’s an application. Do not like.

    Jonathan Feinberg Monday, July 7, 2008 at 10:02 am
  10. Because Option is monadic, there are a *lot* of very nice things you can do with it, besides just emulating the elvis operator. I must admit, I wasn’t aware of getOrElse, but I do use map a lot (similar to Reganwald’s andand for Ruby).

    @Jesper

    An implicit conversion from T to Option[T] isn’t a bad idea, even in the general sense. The process of “boxing” a value into an Option is ridiculously common, and yet the boiler-plate for it is fairly tedious. Obviously, such a conversion isn’t worthy of its own library, but it’s definately a useful one that should be kept around. Specifically:

    implicit def val2option[T](value: T) = if (value == null) None else Some(value)

    @Labaru

    I wasn’t aware that Perl had the || operator in this fashion, but it makes sense. Ruby too implements something similar, though it is more common to use it as an assignment:

    lastName ||= ‘Spiewak’

    Obviously, if you’re trying to stick with immutable data though, the above is less preferable to the straight-up operator.

    @DavidLG

    That syntax is quite nice actually. Sort of like a soft cast. I’m not sure whether I like it better or not, but it’s certainly more general. Also, it would allow me to get rid of the temporary constant altogether in the spec without accidentally testing the type unification in two places. Thanks for the tip!

    @Jonathan

    Pass-by-name seems quite fragile when you first look at it, but in truth, it’s no more (or less) fragile than a simple closure. In fact, that’s how Scala implements things under the surface. For example:

    def doSomething(res: =>String) = println(res)
    doSomething(“Daniel”)

    …is translated into:

    def doSomething(res: ()=>String) = println(res())
    doSomething(() => “Daniel”)

    It’s mainly just syntax sugar. I can certainly agree that it shouldn’t be over-used. In an imperative design, strange things can happen when you expect certain side-effects to run and they don’t (sometimes). However, if your design is more functional in nature (specifically with referential transparency) then it really isn’t a problem at all and pass-by-name can be a nice peformance boost.

    Pass-by-name also allows for some interesting (if useless) applications such as this one from Scala by Example:

    def While(pred: =>Boolean)(body: =>Any) {
    if (pred) {
    body
    While(pred)(body)
    }
    }

    Usage example:

    var a = 1
    While(a < 10) {
    println(a)
    a += 1
    }

    Without pass-by-name (or the more verbose equivalent closure syntax), the above would be impossible. This is because the predicate (and the body) must be evaluated multiple times, rather than just once at call-point.

    Daniel Spiewak Monday, July 7, 2008 at 10:14 am
  11. Well Ruby also has ||= (after all it is Perl++ according to some ;-) ).
    Just to be clear, Groovy’s elvis operator takes advantage of the Groovy truth, meaning that the left expression is not tested solely on is ‘nullable state’, for example an empty Map or List will also evaluate to false, thus the elvis operator will return the right expression. This clearly complicates things in the Scala version as in order to replicate the full behavior of ?: (or even || in Perl) it must take into account other types and its rules.

    Regardless of that, I think Daniel has demonstrated that Scala has a powerful mechanism for defining new operators if you need them. Good read!

    Andres Almiray Monday, July 7, 2008 at 12:01 pm
  12. You wanna try implementing Groovy’s safe-dereference operator (?.) next?

    http://groovy.codehaus.org/Null+Object+Pattern

    Antony Stubbs Monday, July 7, 2008 at 12:29 pm
  13. @Antony

    Actually, I looked at doing that one first. Or rather, I was trying to replicate Ragenwald’s andand “operator” from Ruby land. The problem is, this is a bit difficult to do without proxies. Consider the following expression (using Ruby’s andand, but it’s the same with Groovy’s operator):

    test.andand().doSomething()

    I could create an implicit conversion from Any => some type implementing the andand() method, but that’s where the magic stops. Regardless of whether the value is null or not, the doSomething() method will still execute. Since it has to execute on some target in a type-safe manner, that would require the implementation of a bytecode proxy, which would be flaky and weird (problems with annotations, final methods, constructors, etc).

    A better alternative is to go back to the source of inspiration for both andand as well as Groovy’s safe dereference operator: the monadic map operation. The following is some Scala syntax which uses Option to implement the pattern:

    val something: Option[String] = … // presumably could be either Some(…) or None

    val length = something.map(_.length)

    After this, `length` either be Some(str.length) (where str is the String object contained within the Option), or None. This is exactly how the safe-dereferencing operator works, except it uses null rather than a type-safe monad.

    As pointed out above, we could define an implicit conversion from some type T => Option[T] and then map in that fashion, but some types already have map defined, so it wouldn’t be very useful. Alternatively, I could implement something similar to map but with a separate name, but any way it is implemented, it will rely upon a higher-order function rather than a simple chained call. It seems to be just the nature of statically typed languages (if anyone has a way around this, feel free to correct me).

    Daniel Spiewak Monday, July 7, 2008 at 1:42 pm
  14. Bah. (defun :? (x y) (if (null x) y x)) (print (:? theName “Elvis”))

    web design Wednesday, July 9, 2008 at 2:22 pm
  15. Well, we can’t *all* be Lisp. :-)

    Daniel Spiewak Wednesday, July 9, 2008 at 2:23 pm
  16. Hi,

    Very nice article. However, the coalescingOperator in the zip file is not working for me:

    Welcome to Scala version 2.7.1.final (Java HotSpot(TM) Client VM, Java 1.6.0_02).
    Type in expressions to have them evaluated.
    Type :help for more information.

    scala> implicit def coalescingOperator[T](pred: T) = new { def ??[A >: T](alt: =>A) = if (pred == null) alt else pred }
    implicit def coalescingOperator[T](pred: T) = new { def ??[A >: T](alt: =>A) = if (pred == null) alt else pred }
    coalescingOperator: [T](T)java.lang.Object{def ??[A >: T](=> A): A}

    scala> 1 ?? 2
    1 ?? 2
    res0: Int = 1

    scala> null ?? 1
    null ?? 1
    :6: error: value ?? is not a member of Null
    null ?? 1
    ^

    I can’t quite make it work… any ideas?

    Victor Rodriguez Wednesday, July 23, 2008 at 11:29 am
  17. Null is a bit of a special type. Implicit conversions don’t work properly on it. I’m sure there’s some deep theoretical reason why this is so, but as far as I’m concerned, it’s an annoying limitation. :-)

    You have to do something like this to really test:

    val i: Int = null
    i ?? 1

    Since you would never actually use coalescence on null itself, I think this is a fairly workable limitation. :-)

    Daniel Spiewak Wednesday, July 23, 2008 at 12:01 pm
  18. Thanks for the response Daniel regarding ?. I think I missed it!
    I think I understand what you’re proposing, but what about something like this, assuming you don’t have control over the sources:
    company?.getContactPerson?.getContactDetails?.getAddress?.getCity
    Say it’s a java bean and you can’t go in and change the return values to Something[T] – what can we do there?

    Antony Stubbs Tuesday, July 21, 2009 at 8:07 pm
  19. oh gosh – ok on re-read that’s where you’re proposing the implicit conversion from T to Option[T] right? But would you still be able to chain it together like that? You’d still need the map right? hmm….
    var city = company.map(_.getContactPerson.map(_.getContactDetails.map(_.getAddress.map(_.getCity))))
    ?

    Antony Stubbs Tuesday, July 21, 2009 at 8:10 pm
  20. @Antony

    We can’t really do much of anything in the case of company?.getContactPerson, etc… Even assuming this were valid Scala syntax, we would still need some way to prevent the later calls in the chain. This is not possible if we’re not using function values. Thus, something like map is really the only option.

    An implicit conversion to Option wouldn’t be bad, but by making things implicit, we’re circumventing some of the protection of the type system. The best way to do this sort of thing is to use for-comprehensions in concert with Option. We can do map and flatMap, but it’s much nicer with magical syntax:

    for {
      c < - company
      person <- c.getContactPerson
      details <- person.getContactDetails
      address <- details.getAddress
    } yield address.getCity
    Daniel Spiewak Tuesday, July 21, 2009 at 9:28 pm
  21. Another way to tackle this issue could be:

    object ?{ def apply[T](t : T) = if (t == null) None else Some(t) }

    ?(expression).getOrElse { error(“can’t be null”) }

    Hope you like it ;)

    Pawel Badenski Wednesday, August 26, 2009 at 12:09 pm
  22. I think that I probably would have kept ? as a method rather than an object. However, your approach does have the advantage of being importable at the top-level. At least until we get package objects (Scala 2.8), that would probably be the way to go.

    Daniel Spiewak Wednesday, August 26, 2009 at 12:16 pm
  23. I submit this simple code snippet:

    def whilst(pred : =>Bool)(body : => Unit) : Unit = {
    if (pred) {
    body
    whilst(pred, body)
    }
    }

    def loop(body : => Unit)(control : (=> Unit) => Unit) = {
    body
    control(body)
    }

    var x = 0
    loop {
    print(x)
    } while( (x += 1) < 10)

    Tadaaa!

    anonymous Thursday, September 9, 2010 at 5:43 pm
  24. oops…

    should be

    var x = 0
    loop {
    print(x)
    } whilest( (x += 1) < 10)

    anonymous Thursday, September 9, 2010 at 5:45 pm
  25. I think chained flatMaps are cleaner than for-comprehensions, since you don’t need a new variable name for each step.

    (company flatMap _.getContactPerson
    flatMap _.getContactDetails
    flatMap _.getAddress
    flatMap _.getCity) match {
    case Some(city) => …
    case None => …
    }

    If nullable values are required for Java interoperability, here’s an approach that provides safety without NPE-wrangling or too much clutter:

    sealed trait Nullable[+A] {
    def apply[B](f:A=>B): Nullable[B]
    }

    def ?[A](a: A) = a match {
    case null => NullRef
    case _ => Ref(a)
    }

    case class Ref[A](value: A) extends Nullable[A] {
    def apply[B](f:A=>B) = ?(f(value))
    }

    object NullRef extends Nullable[Nothing] {
    def apply[B](f: Nothing=>B): Nullable[B] = NullRef
    }

    ?(company)(_.getContactPerson)(_.getContactDetails)(_.getAddress)(_.getCity) match {
    case Ref(city) => …
    case _ => …
    }

    It shouldn’t be hard to expand Nullable into a full Option-style monad, if desired.

    D. Gates Saturday, January 29, 2011 at 10:20 am

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*