I would like to simplify this:
var countA: Int = 0
var countB: Int = 0
if (validItem) {
if (region.equalsIgnoreCase( "US" )) {
if (itemList > 0) {
countB = 1
} else {
countA = 1
}
} else {
countB = 1
}
} else {
countA = 1
}
How do I use ternary operator in scala.
This might be a bit confusing for a "newbie", but you could attach a ternary method to the Boolean
class like so.
implicit class Ternary[T](condition: Boolean) {
def ??(a: => T, b: => T): T = if (condition) a else b
}
Usage:
(4 == 4)??("yes","no") // res0: String = yes
("abc".length < 2).??(1,0) // res1: Int = 0
List('c').isEmpty.??('X','+') // res2: Char = +
You should not need to use a ternary operator in Scala. In Scala, if
is an expression not a statement, you can say val x = if (b) 1 else 2
.
The usage of var
in your example also points to a problem, because you can usually avoid this when you use the if
as an expression.
Let's try to break down the code to avoid the var
, i.e. first remove all if
statements that are not expressions with a corresponding else
and always provide both values:
var countA: Int = ???
var countB: Int = ???
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) {
countA = 0
countB = 1
} else {
countA = 1
countB = 0
}
} else {
countA = 0
countB = 1
}
} else {
countA = 1
countB = 0
}
Now we can define the condition for which either of countA
and countB
is one:
val isUS = region.equalsIgnoreCase("US")
val hasItems = itemList > 0
val isA = !validItem || (isUS && !hasItems)
val isB = !isA
// or: val isB = validItem && (!isUS || hasItems)
and then:
val countA = if (isA) 1 else 0
val countB = if (isB) 1 else 0
To expand on @0__'s answer (if that is his/her real name), you can also use tuples to assign to two variables at once.
val (countA, countB) =
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) (0,1) else (1,0)
} else {
(0,1)
}
} else {
(1,0)
}
I think the short answer is that in Scala there is no ?:
ternary operator. Although you can imitate the syntax using implicits (see @jwvh's answer), I think it doesn't really simplify anything.
There are a couple of important properties of the conventional ?:
- it always has two branches
following from the previous property, the ternary operator always returns a value (this is mostly the point of using ?:
)
val result: Int = if (true) 1 else 2
// result is 1
branches are evaluated lazily
if (true) 1 else (0/0) // returns 1
if (false) 0/0 else 2 // returns 2
// i.e. 0/0 is not evaluated
As you see, in Scala if-else
(with else
) construction satisfies these properties. This is not the case for if-else
construction in some other languages, like C or Java, because it doesn't return a value.
So the bottom line is that in Scala
you don't need a ternary operator, because you can just use if-else
.
UPDATE
As Alexey Romanov mentions in the comments, if
statement without else
actually satisfies the first condition as well. When you write
val result = if (true) 1
it actually means if (true) 1 else ()
, so result
will have type AnyVal
instead of Int
, because the return type of the if
expression is the lowest common bound of the both branches (Int
and Unit
in this case).