Reputation: 198258
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?
Upvotes: 1
Views: 176
Reputation: 207
Nothing is wrong. { } around a single statement doesn't make any changes to the code. Remember, the result of a block is the result of the last statement, so if you have just one, you can also omit the { }. But even if you had multiple statements, the & is binding first, see as an example
if (false) {true; 1} else {false; 3} & {true; 2}
The result is 2 (the result of 3&2).
Upvotes: 1
Reputation: 3530
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.
Upvotes: 1