В этом уроке вы узнаете:
Давайте создадим две полезные функции:
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 в качестве аргумента!