К сожалению, (единственного) существующего ответа мало на сочные биты, и ссылки в комментарии не работают. Итак, позвольте мне попытаться добавить сюда немного сока, если не по какой-либо другой причине, это моя собственная справочная информация, когда я на самом деле решу что-то сделать с этим в будущем, учитывая, что этот ответ находится в верхней части каждого поиска в Google, который я выполняю.
Виртуализированное сопоставление с образцом, как уже упоминалось, представляет собой переписывание того, как компилятор Scala обрабатывает сопоставление с образцом. Он служил многим целям, с частью «виртуализации», означающей, что он является частью виртуализированного проекта scala. Это усилие немного противоположно макросам: оно берет вещи, которые «запускаются» во время компиляции, а затем перемещаются во время выполнения.
Например, учитывая наличие правильного определения в области видимости, выражение вроде этого:
if (false) 1 else 2
вместо того, чтобы компилироваться в ветви и литералы байт-кода или даже оптимизироваться до литерала "2", фактически компилируется как следующий оператор:
__ifThenElse(false, 1, 2)
Пожалуйста, смотрите scala virtualized wiki для получения дополнительной информации и некоторых примеров того, для чего это может быть полезно.
Однако я сказал, что переписывание шаблонов соответствовало многим целям. Еще одна очень важная цель состояла в том, чтобы превратить код спагетти, который был старым сопоставителем шаблонов, полными или специальными и угловыми случаями и ошибками, во что-то, что можно легче обосновывать, расширять и улучшать. Эта перезапись исправила так много проблем, что люди просто просмотрели список проблем, запустив пример кода для проблем, связанных с сопоставителем шаблонов и пометив проблемы как «исправленные» в процессе работы. У него есть новые ошибки, но в гораздо меньшем масштабе.
Теперь очень мало информации о том, как работает новый сопоставитель шаблонов, но, по сути, он преобразуется в несколько вызовов методов, которые «реализуются» в компиляторе с монадой Option
. Затем он переходит в фазу оптимизации, которая производит оптимальный байт-код.
Можно ввести свой собственный сопоставитель, хотя он заблокирован флагом -Xexperimental
. Попробуйте следующий код, скопированный из набора тестов Scala, с этим флагом и без него:
trait Intf {
type Rep[+T]
type M[+T] = Rep[Maybe[T]]
val __match: Matcher
abstract class Matcher {
// runs the matcher on the given input
def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U]
def zero: M[Nothing]
def one[T](x: Rep[T]): M[T]
def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T]
def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] // used for isDefinedAt
}
abstract class Maybe[+A] {
def flatMap[B](f: Rep[A] => M[B]): M[B]
def orElse[B >: A](alternative: => M[B]): M[B]
}
implicit def proxyMaybe[A](m: M[A]): Maybe[A]
implicit def repInt(x: Int): Rep[Int]
implicit def repBoolean(x: Boolean): Rep[Boolean]
implicit def repString(x: String): Rep[String]
def test = 7 match { case 5 => "foo" case _ => "bar" }
}
trait Impl extends Intf {
type Rep[+T] = String
object __match extends Matcher {
def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] = ("runOrElse("+ in +", ?" + matcher("?") + ")")
def zero: M[Nothing] = "zero"
def one[T](x: Rep[T]): M[T] = "one("+x.toString+")"
def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T] = "guard("+cond+","+then+")"
def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] = ("isSuccess("+x+", ?" + f("?") + ")")
}
implicit def proxyMaybe[A](m: M[A]): Maybe[A] = new Maybe[A] {
def flatMap[B](f: Rep[A] => M[B]): M[B] = m + ".flatMap(? =>"+ f("?") +")"
def orElse[B >: A](alternative: => M[B]): M[B] = m + ".orElse("+ alternative +")"
}
def repInt(x: Int): Rep[Int] = x.toString
def repBoolean(x: Boolean): Rep[Boolean] = x.toString
def repString(x: String): Rep[String] = x
}
object Test extends Impl with Intf with App {
println(test)
}
Результат без флага - это то, что вы ожидаете:
scala> Test.main(null)
bar
С -Xexperimental
, однако, альтернативный соответствующий «движок» компилируется:
scala> Test.main(null)
runOrElse(7, ?guard(false,?).flatMap(? =>one(foo)).orElse(one(bar)))
См. Также для получения дополнительной информации скалярные документы для PatternMatching и MatchMonadInterface .
Отказ от ответственности: вышеупомянутое было извлечено и запущено из версии Scala в основной ветке, после 2.10.0, так что могут быть различия. Мне, к сожалению, не хватает чистой среды 2.10.0 или 2.10.1, чтобы проверить это.