scalabook

Форк
0
/
functions-are-values.md 
122 строки · 5.6 Кб

Функции - это значения

Хотя каждый когда-либо созданный язык программирования, вероятно, позволяет писать чистые функции, вторая важная особенность ФП на Scala заключается в том, что функции можно создавать как значения, точно так же, как создаются значения String

и Int
.

Эта особенность содержит много преимуществ, наиболее распространенными из которых являются:

  • можно определять методы, принимающие в качестве параметров функции
  • можно передавать функции в качестве параметров в методы

Это было видно во многих местах предыдущих глав, когда демонстрировались такие методы, как map

и filter
:

val nums = (1 to 10).toList
// nums: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val doubles = nums.map(_ * 2)
// doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
val lessThanFive = nums.filter(_ < 5)
// lessThanFive: List[Int] = List(1, 2, 3, 4)

В этих примерах анонимные функции передаются в map

и filter
.

Анонимные функции также известны как лямбды.

Помимо передачи анонимных функций в filter

и map
, в них также можно передать методы:

def double(i: Int): Int = i * 2
def underFive(i: Int): Boolean = i < 5
val doubles = nums.filter(underFive).map(double)
// doubles: List[Int] = List(2, 4, 6, 8)

Эта возможность обращаться с методами и функциями как со значениями — мощное свойство, предоставляемое языками функционального программирования.

Технически функция, которая принимает другую функцию в качестве входного параметра, известна как функция высшего порядка.

Функции, анонимные функции и методы

В примерах выше анонимная функция это:

_ * 2

Как было показано в обсуждении функций высшего порядка, _ * 2

- сокращенная версия синтаксиса:

(i: Int) => i * 2

Такие функции называются "анонимными", потому что им не присваивается определенное имя. Для того чтобы это имя задать, достаточно просто назначить его переменной:

val double = (i: Int) => i * 2

Теперь появилась именованная функция, назначенная переменной double

. Можно использовать эту функцию так же, как используется метод:

double(2)
// res1: Int = 4

В большинстве случаев не имеет значения, является ли double

функцией или методом; Scala позволяет обращаться с ними одинаково. За кулисами технология Scala, которая позволяет обращаться с методами так же, как с функциями, известна как Eta Expansion.

Эта способность беспрепятственно передавать функции в качестве переменных является отличительной чертой функциональных языков программирования, таких как Scala. И, как было видно на примерах map

и filter
, возможность передавать функции в другие функции помогает создавать код, который является кратким и при этом читабельным — выразительным.

Вот еще несколько примеров:

List("bob", "joe").map(_.toUpperCase)
// res2: List[String] = List("BOB", "JOE")
List("bob", "joe").map(_.capitalize)
// res3: List[String] = List("Bob", "Joe")
List("plum", "banana").map(_.length)
// res4: List[Int] = List(4, 6)
val fruits = List("apple", "pear")
// fruits: List[String] = List("apple", "pear")
fruits.map(_.toUpperCase)
// res5: List[String] = List("APPLE", "PEAR")
fruits.flatMap(_.toUpperCase)
// res6: List[Char] = List('A', 'P', 'P', 'L', 'E', 'P', 'E', 'A', 'R')
val nums = List(5, 1, 3, 11, 7)
// nums: List[Int] = List(5, 1, 3, 11, 7)
nums.map(_ * 2)
// res7: List[Int] = List(10, 2, 6, 22, 14)
nums.filter(_ > 3)
// res8: List[Int] = List(5, 11, 7)
nums.takeWhile(_ < 6)
// res9: List[Int] = List(5, 1, 3)
nums.sortWith(_ < _)
// res10: List[Int] = List(1, 3, 5, 7, 11)
nums.sortWith(_ > _)
// res11: List[Int] = List(11, 7, 5, 3, 1)
nums.takeWhile(_ < 6).sortWith(_ < _)
// res12: List[Int] = List(1, 3, 5)

Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.