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 .