Search code examples
scalaif-statementlift

`if else` with or without `()` behaviors different in css transformer of Lift?


The lift code:

import net.liftweb.util.Helpers._

object test extends App {

  val xml = <div>
    <span name="a">a</span>
    <span name="b">b</span>
  </div>

  val t1 = if (true) {
    "@a" #> "xxx"
  } else {
    "@a" #> "yyy"
  } &
    "@b" #> "zzz"

  val t2 = (if (true) {
    "@a" #> "xxx"
  } else {
    "@a" #> "yyy"
  }) &
    "@b" #> "zzz"

  println("------------- t1 ------------")
  println(t1(xml))

  println("------------- t2 ------------")
  println(t2(xml))

}

The output:

------------- t1 ------------
<div>
    xxx
    <span name="b">b</span>
  </div>
------------- t2 ------------
<div>
    xxx
    zzz
  </div>

Strange, right? The only difference is that the t2 has wrapped if else with ().

My friend decompiled the bytecode and found that scala has compiled the t1 similar to:

t1 = true ? "@a" #> "xxx" : "@a" #> "yyy" & "@b" #> "zzz"

As if the code is:

 if (true) 
    "@a" #> "xxx"
  else 
    "@a" #> "yyy" &
    "@b" #> "zzz"

Where is wrong?


Solution

  • I guess it has to do with the operator precedence and the way code is parsed. To get a very precise answer one would have to look closely at Scala's spec.

    In general, I would recommend to write a function for @a and another for @b to make things really clear when reading code. E.g.:

    def ta = 
      if (true) "@a" #> "xxx"
      else "@a" #> "yyy"
    
    def tb = "@b" #> "zzz"
    
    val t1 = ta & tb
    

    Scala has a very lightweight syntax that encourages such definition unlike many other programming language. Your code tend to be much more readable when using it. Have a look at Odersky's talk on Scala with Style. He explains other interesting tricks too.