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 | q
Then 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
Note that the operator precedence does not match Java’s, so you’ll have to parenthesise most calls to this.
Nice, why didn’t I think of that?
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…
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.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)
Thanks Tony. This is what a lot of us imperative language programmers need – small bits of code that illustrate practical uses of functional concepts. In this case, higher-order and partially-applied functions.
I played around with the code and got it to work after 2 small modifications:
1) The implicit statement must create a Bool(b) instance:
implicit def BooleanBool(b: Boolean) = new Bool(b)
2) As mentioned by jherber above, we need a type for the argument not supplied:
var t = (_:Boolean) ? b | c
Does this make sense or am I missing something?
Hello Atif,
This post was written when Scala was around version 2.4.0 and has since undergone some significant changes. It is highly likely that you may need to make small modifications for this code to work on the latest version. Hope it helps
It does help. I guess it should be noted that I am running Scala version 2.7.3. Thanks.