Любой объектно-ориентированный язык (или любой язык с полиморфизмом времени выполнения) могут реализовывать условные выражения как библиотечную функцию, поскольку диспетчеризация метода уже является более общей формой условных вычислений в любом случае. Например, Smalltalk не имеет абсолютно никаких условий, кроме отправки по методу.
Нет необходимости в какой-либо магии компилятора, кроме, возможно, синтаксического удобства.
В Scala это может выглядеть примерно так:
trait MyBooleanLike {
def iff[T <: AnyRef](thenn: => T): T
def iffElse[T](thenn: => T)(els: => T): T
def &&(other: => MyBoolean): MyBoolean
def ||(other: => MyBoolean): MyBoolean
def nott: MyBoolean
}
trait MyTruthiness extends MyBooleanLike {
def iff[T](thenn: => T) = thenn
def iffElse[T](thenn: => T)(els: => T) = thenn
def &&(other: => MyBoolean) = other
def ||(other: => MyBoolean) = MyTrue
def nott = MyFalse
}
trait MyFalsiness extends MyBooleanLike {
def iff[T](thenn: => T): T = null.asInstanceOf[T]
def iffElse[T](thenn: => T)(els: => T) = els
def &&(other: => MyBoolean) = MyFalse
def ||(other: => MyBoolean) = other
def nott = MyTrue
}
abstract class MyBoolean extends MyBooleanLike
class MyTrueClass extends MyBoolean with MyTruthiness {}
class MyFalseClass extends MyBoolean with MyFalsiness {}
object MyTrue extends MyTrueClass {}
object MyFalse extends MyFalseClass {}
Просто добавьте небольшое неявное преобразование:
object MyBoolExtension {
implicit def boolean2MyBoolean(b: => Boolean) =
if (b) { MyTrue } else { MyFalse }
}
import MyBoolExtension._
И теперь мы можем использовать его:
object Main extends App {
(2 < 3) iff { println("2 is less than 3") }
}
[Примечание: мой тип-фу довольно слабый. Мне пришлось немного обмануть, чтобы компилировать это в разумные сроки. Кто-то с лучшим пониманием системы типов Scala может захотеть исправить это. Кроме того, теперь, когда я смотрю на это, 8 классов, черты и объекты, два из которых абстрактные, кажутся немного перегруженными ;-)]
Конечно, то же самое верно и для сопоставления с образцом. Любой язык с сопоставлением с образцом не нуждается в других видах условных выражений, поскольку сопоставление с образцом в любом случае является более общим.
[Кстати: это в основном порт этого кода Ruby Я написал пару лет назад для забавы.]