Даже если синтаксис не оценивается в ожидаемом порядке - он связывает условное обозначение с первым вариантом! - вы можете создать свой собственный троичный оператор, например так:
class IfTrue[A](b: => Boolean, t: => A) { def |(f: => A) = if (b) t else f }
class MakeIfTrue(b: => Boolean) { def ?[A](t: => A) = new IfTrue[A](b,t) }
implicit def autoMakeIfTrue(b: => Boolean) = new MakeIfTrue(b)
Хитрость заключается в том, чтобы интерпретировать ?
как метод объекта MakeIfTrue
, который связывает условие с объектом для возврата в «истинном» случае. Полученный объект IfTrue
теперь использует метод |
в качестве запроса для оценки условия, возвращая сохраненную опцию true, если условие истинно, или только что переданную, если она ложна.
Обратите внимание, что я использовал такие вещи, как => A
вместо просто A
- параметры по имени - чтобы не вычислять выражение, если оно на самом деле не используется. Таким образом, вы будете оценивать только ту сторону, которая вам действительно нужна (точно так же, как утверждение if).
Давайте посмотрим на это в действии:
scala> List(1,3,2).isEmpty ? "Empty" | "Nonempty"
res0: java.lang.String = Nonempty
scala> (4*4 > 14) ? true | false
res1: Boolean = true
scala> class Scream(s: String) { println(s.toUpperCase + "!!!!") }
defined class Scream
scala> true ? new Scream("true") | new Scream("false")
TRUE!!!!
res3: Scream = Scream@1ccbdf7
(P.S. Чтобы избежать путаницы с библиотекой Actor ?
, вы, вероятно, должны называть это как-то еще как |?
.)