Does Scala have Java’s ternary operator?
I hear this question a lot. Yes it does. Instead of c ? p : q, it is written if(c) p else q.
This may not be preferable. Perhaps you’d like to write it using the same syntax as Java. Sadly, you can’t. This is because : is not a valid identifier. Fear not, | is! Would you settle for this?
c ? p | qThen you’ll need the following code. Notice the call-by-name (=>) annotations on the arguments. This evaluation strategy is required to correctly rewrite Java’s ternary operator. This cannot be done in Java itself.
case class Bool(b: Boolean) { def ?[X](t: => X) = new { def |(f: => X) = if(b) t else f } } object Bool { implicit def BooleanBool(b: Boolean) = Bool(b) }
Here is an example using the new operator that we just defined:
object T { val condition = true import Bool._ // yay! val x = condition ? "yes" | "no" }
Have fun ![]()
October 13th, 2008 at 7:08 pm
Note that the operator precedence does not match Java’s, so you’ll have to parenthesise most calls to this.
October 14th, 2008 at 8:27 am
Nice, why didn’t I think of that?
October 29th, 2008 at 7:37 pm
And the big question is “do we really need it ?”. “if a else b” is a nice Scala idiom, and in my opinion introducing “a ? b | c” is just bringing old habits to a new environment. It doesn’t really hurt in this case but I can resist the feeling it’s some sort of a bad smell…
October 30th, 2008 at 6:15 am
Pawel, Yes it is needed. Not because of the terser syntax (I happen to prefer it though), but because it allows composition of the smaller parts.
e.g.
val t = _ ? b | cis a function that takes a boolean and returns the least common superclass of b and c. In other words ‘if’ should be a regular function (which the compiler optimises), not a language specialty. The bad habit here, is copying older languages without call-by-name semantics by making it a language feature.November 7th, 2008 at 2:59 pm
anyone else care for the look of R’s ifelse function?
def ifelse[U](c:Boolean, t_exp: =>U, f_exp: =>U) = if (c) t_exp else f_exp
val x = ifelse(condition, “true”, “false”) // no parenthesis corner cases
val x = condition ? “true” | “false”
unfortunately, scala doesn’t infer the type on the partial
val t = ifelse( _:Boolean, b, c)