Являются ли шаблоны для Scala первым классом?
Можно ли передавать шаблоны случаев в качестве параметров другим функциям? Что-то вроде этого:
def foo(pattern: someMagicType) {
x match {
pattern => println("match")
}
}
def bar() {
foo(case List(a, b, c))
}
3 ответа
Я думаю, что первый ответ Ким Стебель близок к тому, что вы хотите. "Соответствие шаблону как таковое" не является изолированным объектом в Scala. Совпадение может быть определено как Function1
или же PartialFunction
,
def foo[A, B](x: A)(pattern: PartialFunction[A, B]): Unit =
if(pattern.isDefinedAt(x)) println("match")
def bar(list: List[String]): Unit =
foo(list){ case List("a", "b", "c") => }
Тестовое задание:
bar(Nil)
bar(List("a", "b", "c"))
В качестве альтернативы используйте состав:
def foo[A, B](x: A)(pattern: PartialFunction[A, B]): Unit = {
val y = pattern andThen { _ => println("match")}
if (y.isDefinedAt(x)) y(x)
}
Итак, вы хотите передать блок сопоставления с образцом в другую функцию? Это можно сделать с PartialFunction
s, как показано в следующем примере:
def foo(f:PartialFunction[String, Int]) = {
f("")
}
foo {
case "" => 0
case s => s.toInt
}
Ваш магический тип может быть записан как структурный тип с неприменимым методом. В зависимости от того, какой экстрактор вам нужен, вам понадобятся разные unapply
или же unapplySeq
, Ниже приведен простой пример.
def foo(x:Int, Pattern: { def unapply(x:Int):Boolean }) {
x match {
case Pattern => println("match")
}
}
foo(1, new { def unapply(x:Int) = x > 0 })
И вот как это делается для списков:
foo(List(1,2,3), new { def unapplySeq(x:List[Int]):Option[List[Int]] = if (x.size >= 3) Some(x) else None })
def foo(x:List[Int], Pattern: { def unapplySeq(x:List[Int]):Option[List[Int]] }) {
x match {
case Pattern(a,b,c) => println("match: " + a + b + c)
}
}