Трейт PartialFunction.PartialFunction
трейт PartialFunction[-A, +B] extends A => B
Частичная функция типа PartialFunction[A, B] — это унарная функция, область определения которой не обязательно включает все значения типа A. Функция isDefinedAt позволяет динамически проверить, находится ли значение в области определения функции.
Даже если isDefinedAt возвращает true для a: A, вызов apply(a) может всё равно вызвать исключение, поэтому следующий код является корректным:
val f: PartialFunction[Int, Any] = { case x => x / 0 } // ArithmeticException: / by zero
Ответственность вызывающей стороны — вызвать isDefinedAt перед вызовом apply, потому что если isDefinedAt ложно, не гарантируется, что apply выбросит исключение, чтобы указать ошибку. Если исключение не выброшено, вычисление может привести к произвольному значению.
Обычный способ соблюдения этого контракта — вызвать applyOrElse, который, как ожидается, будет более эффективным, чем вызов как isDefinedAt, так и apply.
Основное различие между PartialFunction и scala.Function1 заключается в том, что пользователь PartialFunction может выбрать другой способ обработки входных данных, которые не входят в область определения. Например:
val sample = 1 to 10
def isEven(n: Int) = n % 2 == 0
val eveningNews: PartialFunction[Int, String] = {
case x if isEven(x) => s"$x is even"
}
// The method collect is described as "filter + map"
// because it uses a PartialFunction to select elements
// to which the function is applied.
val evenNumbers = sample.collect(eveningNews)
val oddlyEnough: PartialFunction[Int, String] = {
case x if !isEven(x) => s"$x is odd"
}
// The method orElse allows chaining another PartialFunction
// to handle input outside the declared domain.
val numbers = sample.map(eveningNews orElse oddlyEnough)
// same as
val numbers = sample.map(n => eveningNews.applyOrElse(n, oddlyEnough))
val half: PartialFunction[Int, Int] = {
case x if isEven(x) => x / 2
}
// Calculating the domain of a composition can be expensive.
val oddByHalf = half.andThen(oddlyEnough)
// Invokes `half.apply` on even elements!
val oddBalls = sample.filter(oddByHalf.isDefinedAt)
// Better than filter(oddByHalf.isDefinedAt).map(oddByHalf)
val oddBalls = sample.collect(oddByHalf)
// Providing "default" values.
val oddsAndEnds = sample.map(n => oddByHalf.applyOrElse(n, (i: Int) => s"[$i]"))
| Примечание |
Дополнительные функции Function, PartialFunction и объекты-экстракторы могут быть преобразованы друг в друга, как показано в следующей таблице.
|
||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Супертипы |
| Известные подтипы | 125 типов |
|---|---|
| Тип "self" |
Абстрактные методы
Source
def isDefinedAt(x: A): Boolean
Проверяет, содержится ли значение в области определения функции.
| Параметры значения |
|
|---|---|
| Возвращает |
|
Конкретные методы
Source
override def andThen[C](k: B => C): PartialFunction[A, C]
Компонует эту частичную функцию с функцией преобразования, которая применяется к результатам этой частичной функции.
Если тип выполнения функции является PartialFunction, то используется другой метод andThen (обратите внимание на его предостережения).
| Параметры типа |
|
|---|---|
| Параметры значения |
|
| Возвращает | частичная функция с областью определения этой частичной функции, возможно суженной заданной функцией, которая отображает аргументы |
| Классы определения | Function1 |
Source
Компонует эту частичную функцию с другой частичной функцией, которая применяется к результатам этой частичной функции.
Обратите внимание, что вызов isDefinedAt для результирующей частичной функции может применить первую частичную функцию и выполнить её побочный эффект. Для повышения эффективности рекомендуется использовать applyOrElse вместо isDefinedAt или apply.
| Параметры типа |
|
|---|---|
| Параметры значения |
|
| Возвращает | частичная функция с областью определения этой частичной функции, суженной другой частичной функцией, которая отображает аргументы |
Source
def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1
Применяет эту частичную функцию к заданному аргументу, когда он содержится в области определения функции. Применяет функцию fallback, когда эта частичная функция не определена.
Обратите внимание, что выражение pf.applyOrElse(x, default) эквивалентно
if(pf isDefinedAt x) pf(x) else default(x)
за исключением того, что метод applyOrElse может быть реализован более эффективно. Для всех литералов частичных функций компилятор генерирует реализацию applyOrElse, которая избегает двойной оценки матчеров шаблонов и условий. Это делает applyOrElse основой для эффективной реализации многих операций и сценариев, таких как:
- комбинирование частичных функций в цепочки orElse/andThen не приводит к избыточной оценке apply/isDefinedAt - lift и unlift не оценивают исходные функции дважды при каждом вызове - runWith позволяет эффективно комбинировать частичные функции с условно применёнными действиями
Для нелитеральных классов частичных функций с нетривиальным методом isDefinedAt рекомендуется переопределить applyOrElse с пользовательской реализацией, которая избегает двойной оценки isDefinedAt. Это может привести к лучшей производительности и более предсказуемому поведению по отношению к побочным эффектам.
| Параметры значения |
|
|---|---|
| Возвращает | результат применения этой функции или функции fallback. |
Source
Компонует другую частичную функцию k с этой частичной функцией так, что эта частичная функция применяется к результатам k.
Обратите внимание, что вызов isDefinedAt для результирующей частичной функции может применить первую частичную функцию и выполнить её побочный эффект. Для повышения эффективности рекомендуется использовать applyOrElse вместо isDefinedAt или apply.
| Параметры типа |
|
|---|---|
| Параметры значения |
|
| Возвращает | частичная функция с областью определения другой частичной функции, суженной этой частичной функцией, которая отображает аргументы |
Source
def elementWise: ElementWiseExtractor[A, B]
Возвращает объект-экстрактор с методом unapplySeq, который извлекает каждый элемент из последовательности данных.
| Пример |
val firstChar: String => Option[Char] = _.headOption
Seq("foo", "bar", "baz") match {
case firstChar.unlift.elementWise(c0, c1, c2) =>
println(s"$c0, $c1, $c2") // Output: f, b, b
}
|
|---|
Source
Преобразует эту частичную функцию в обычную функцию, возвращающую результат Option.
| Возвращает | функцию, которая принимает аргумент |
|---|---|
| См. также | Function.unlift |
Source
Комбинирует эту частичную функцию со вспомогательной частичной функцией, которая применяется в тех случаях, когда эта частичная функция не определена.
| Параметры типа |
|
|---|---|
| Параметры значения |
|
| Возвращает | частичную функцию, область определения которой является объединением областей определения этой частичной функции и |
Source
Комбинирует эту частичную функцию с функцией-действием, которая применяется к результатам этой частичной функции. Функция-действие вызывается только для побочных эффектов; её результат игнорируется.
Обратите внимание, что выражение pf.runWith(action)(x) эквивалентно
if(pf isDefinedAt x) { action(pf(x)); true } else false
за исключением того, что runWith реализована через applyOrElse и, следовательно, потенциально более эффективна. Использование runWith предотвращает двойное вычисление совпадений с шаблонами и условий для литералов частичных функций.
| Параметры значения |
|
|---|---|
| Возвращает | функцию, которая отображает аргументы |
| См. также |
|
Source
Пытается извлечь B из A в выражении сопоставления с образцом.
Наследуемые методы
Source
def apply(v1: A): R
Применяет тело этой функции к аргументу.
| Возвращает | результат применения функции. |
|---|---|
| Наследуется от | Function1 |
Source
def compose[A](g: A => A): A => R
Комбинирует два экземпляра Function1 в новую Function1, при этом эта функция применяется последней.
| Параметры типа |
|
|---|---|
| Параметры значения |
|
| Возвращает | новая функция |
| Унаследовано от | Function1 |
Исходный код
Возвращает строковое представление объекта.
По умолчанию представление зависит от платформы.
| Возвращает | строковое представление объекта. |
|---|---|
| Определяющие классы | Function1 -> Any |
| Унаследовано от | Function1 |
© 2002-2022 EPFL, with contributions from Lightbend.
Licensed under the Apache License, Version 2.0.
https://scala-lang.org/api/3.2.0/scala/PartialFunction.html