В этом уроке вы узнаете:

Объединение функций

Давайте создадим две полезные функции:

scala> def addUmm(x: String) = x + " umm"
addUmm: (x: String)String

scala>  def addAhem(x: String) = x + " ahem"
addAhem: (x: String)String

compose

compose создает новую функцию, которая является объединением других функций f(g(x))

scala> val ummThenAhem = addAhem _ compose addUmm _
ummThenAhem: (String) => String = <function1>

scala> ummThenAhem("well")
res0: String = well umm ahem

andThen

andThen похожа на compose, но сначала вызывается первая функция, затем вторая g(f(x))

scala> val ahemThenUmm = addAhem _ andThen addUmm _
ahemThenUmm: (String) => String = <function1>

scala> ahemThenUmm("well")
res1: String = well ahem umm

Каррирование и Частичный вызов функций

case утверждения

Что же такое case утверждения?

Это подкласс функций, который называется PartialFunction.

Что представляет собой совокупность множества case утверждений?

Это множество объединений PartialFunctions вместе.

Понимание PartialFunction

Функция работает для каждого аргумента определенного типа. Другими словами, функция объявляется как (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.

На прошлой неделе мы увидели нечто любопытное. Мы видели 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 в качестве аргумента!