В этом уроке вы узнаете:
Давайте создадим две полезные функции:
scala> def addUmm(x: String) = x + " umm" addUmm: (x: String)String scala> def addAhem(x: String) = x + " ahem" addAhem: (x: String)String
compose создает новую функцию, которая является объединением других функций f(g(x))
scala> val ummThenAhem = addAhem _ compose addUmm _
ummThenAhem: (String) => String = <function1>
scala> ummThenAhem("well")
res0: String = well umm ahem
andThen похожа на compose, но сначала вызывается первая функция, затем вторая g(f(x))
scala> val ahemThenUmm = addAhem _ andThen addUmm _
ahemThenUmm: (String) => String = <function1>
scala> ahemThenUmm("well")
res1: String = well ahem umm
Это подкласс функций, который называется PartialFunction.
Это множество объединений PartialFunctions вместе.
Функция работает для каждого аргумента определенного типа. Другими словами, функция объявляется как (Int) => String, принимающая любой Int и возвращающая строку.
Частичная функция определена только для определенных значений определенного типа. Частичные функции (Int) => String не может принимать любой Int.
isDefinedAt это метод PartialFunction, который может использоваться, чтобы определить, будет ли PartialFunction принимать данный аргумент.
Заметьте PartialFunction не связана с частично вызываемыми функциями, о которых мы говорили ранее.
Смотрите также: В Effective Scala описывается PartialFunction.
scala> val one: PartialFunction[Int, String] = { case 1 => "one" }
one: PartialFunction[Int,String] = <function1>
scala> one.isDefinedAt(1)
res0: Boolean = true
scala> one.isDefinedAt(2)
res1: Boolean = false
Вы можете использовать частичную функцию.
scala> one(1) res2: String = one
PartialFunctions может быть объединена с чем-то новым, называемым OrElse, который показывает, определен ли PartialFunction с передаваемым аргументом.
scala> val two: PartialFunction[Int, String] = { case 2 => "two" }
two: PartialFunction[Int,String] = <function1>
scala> val three: PartialFunction[Int, String] = { case 3 => "three" }
three: PartialFunction[Int,String] = <function1>
scala> val wildcard: PartialFunction[Int, String] = { case _ => "something else" }
wildcard: PartialFunction[Int,String] = <function1>
scala> val partial = one orElse two orElse three orElse wildcard
partial: PartialFunction[Int,String] = <function1>
scala> partial(5)
res24: String = something else
scala> partial(3)
res25: String = three
scala> partial(2)
res26: String = two
scala> partial(1)
res27: String = one
scala> partial(0)
res28: String = something else
На прошлой неделе мы увидели нечто любопытное. Мы видели case утверждение там, где обычно использовалась функция.
scala> case class PhoneExt(name: String, ext: Int)
defined class PhoneExt
scala> val extensions = List(PhoneExt("steve", 100), PhoneExt("robey", 200))
extensions: List[PhoneExt] = List(PhoneExt(steve,100), PhoneExt(robey,200))
scala> extensions.filter { case PhoneExt(name, extension) => extension < 200 }
res0: List[PhoneExt] = List(PhoneExt(steve,100))
Почему это работает?
filter принимает функцию. В этом случае используется функция-предикат (PhoneExt) => Boolean.
PartialFunction – это подтип Function, поэтому filter может принимать PartialFunction в качестве аргумента!