Scala Language
функции
Поиск…
замечания
Scala имеет первоклассные функции.
Разница между функциями и методами:
Функция не является методом в Scala: функции являются значением и могут быть назначены как таковые. Методы (созданные с использованием def
), с другой стороны, должны принадлежать классу, признаку или объекту.
- Функции компилируются в класс, расширяющий признак (например,
Function1
) во время компиляции и создаются при значении во время выполнения. Методы, с другой стороны, являются членами их класса, признака или объекта и не существуют вне этого. - Метод может быть преобразован в функцию, но функция не может быть преобразована в метод.
- Методы могут иметь параметризацию типа, а функции - нет.
- Методы могут иметь значения параметров по умолчанию, тогда как функции не могут.
Анонимные функции
Анонимные функции - это функции, которые определены, но не назначены.
Ниже приведена анонимная функция, которая принимает два целых числа и возвращает сумму.
(x: Int, y: Int) => x + y
Полученное выражение может быть присвоено val
:
val sum = (x: Int, y: Int) => x + y
Анонимные функции в основном используются в качестве аргументов для других функций. Например, функция map
в коллекции ожидает в качестве аргумента другой функции:
// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
Типы аргументов анонимной функции можно опустить: типы выводятся автоматически :
Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
Если есть только один аргумент, круглые скобки вокруг этого аргумента могут быть опущены:
Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
Подчеркивание сокращений
Существует еще более короткий синтаксис, который не требует имен для аргументов. Вышеприведенный фрагмент можно написать:
Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
_
представляет анонимные аргументы функции позиционно. С анонимной функцией, имеющей несколько параметров, каждое вхождение _
будет ссылаться на другой аргумент. Например, два следующих выражения эквивалентны:
// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)
При использовании этой стенограммы любой аргумент, представленный позицией _
можно ссылаться только один раз и в том же порядке.
Анонимные функции без параметров
Чтобы создать значение для анонимной функции, которая не принимает параметры, оставьте список параметров пустым:
val sayHello = () => println("hello")
Состав
Состав функции позволяет использовать две функции и рассматривать их как одну функцию. Выраженная математическими терминами, заданная функцией f(x)
и функцией g(x)
, функция h(x) = f(g(x))
.
Когда функция скомпилирована, она компилируется в тип, связанный с Function1
. Scala предоставляет два метода в реализации Function1
связанных с композицией: andThen
и compose
. Метод compose
соответствует приведенному выше математическому определению так:
val f: B => C = ...
val g: A => B = ...
val h: A => C = f compose g
andThen
(думаю, h(x) = g(f(x))
) имеет более «DSL-подобное» чувство:
val f: A => B = ...
val g: B => C = ...
val h: A => C = f andThen g
Новая анонимная функция выделяется с закрытой над f
и g
. Эта функция связана с новой функцией h
в обоих случаях.
def andThen(g: B => C): A => C = new (A => C){
def apply(x: A) = g(self(x))
}
Если либо f
либо g
работает через побочный эффект, то вызов h
вызовет все побочные эффекты f
и g
в порядке. То же самое относится к любым изменяемым изменениям состояния.
Связь с PartialFunctions
trait PartialFunction[-A, +B] extends (A => B)
Каждый отдельный аргумент PartialFunction
также является Function1
. Это противоречит интуиции в формальном математическом смысле, но лучше подходит для объектно-ориентированного дизайна. По этой причине Function1
не должен предоставлять постоянный true
метод isDefinedAt
.
Чтобы определить частичную функцию (которая также является функцией), используйте следующий синтаксис:
{ case i: Int => i + 1 } // or equivalently { case i: Int ⇒ i + 1 }
Для получения дополнительной информации ознакомьтесь с PartialFunctions .