Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a ternary operator in Scala which preserves leading tokens?

I'm writing a code generator which produces Scala output.

I need to emulate a ternary operator in such a way that the tokens leading up to '?' remain intact.

e.g. convert the expression c ? p : q to c something. The simple if(c) p else q fails my criteria, as it requires putting if( before c.

My first attempt (still using c/p/q as above) is

c match { case(true) => p; case _ => q }

another option I found was:

class ternary(val g: Boolean => Any) { def |: (b:Boolean) = g(b) }

implicit def autoTernary (g: Boolean => Any): ternary = new ternary(g)

which allows me to write:

c |: { b: Boolean => if(b) p else q }

I like the overall look of the second option, but is there a way to make it less verbose?

Thanks

like image 609
Alex R Avatar asked Apr 24 '10 19:04

Alex R


1 Answers

Ternary operator which adds my improvement to the best of Rex Kerr’s and Michel Krämer’s implementations:

  • My improvement to use Scala’s new value class to avoid boxing overhead.
  • Call by-name on 2nd and 3rd operands so only the chosen one is evaluated.
  • Michel’s call by-value on the 1st (Boolean) operand to avoid by-name overhead; it is always evaluated.
  • Rex’s concrete class for the condition to avoid any anonymous class overhead.
  • Michel’s evaluation of the condition to determine which class to construct to avoid of overhead of a two argument constructor.

.

sealed trait TernaryResult[T] extends Any {
  def |(op3: => T): T
}

class Ternary2ndOperand[T](val op2: T) extends AnyVal with TernaryResult[T] {
  def |(op3: => T) = op2
}

class Ternary3rdOperand[T](val op2: T) extends AnyVal with TernaryResult[T] {
  def |(op3: => T) = op3
}

class Ternary(val op1:Boolean) extends AnyVal {
   def ?[A](op2: => A): TernaryResult[A] = if (op1) new Ternary2ndOperand(op2) else new Ternary3rdOperand(op2)
}

object Ternary {
   implicit def toTernary(condition: Boolean) = new Ternary(condition)
}

Note the improvement over if else is not just the 6 characters saved. With Scala IDE’s syntax coloring on keywords being the same (e.g. purple) for if, else, null, and true, there is better contrast in some cases (which isn't shown by the syntax coloring below as currently rendered on this site):

if (cond) true else null
cond ? true | null
like image 169
Shelby Moore III Avatar answered Oct 21 '22 08:10

Shelby Moore III