Неизменяемые значения
В чистом функциональном программировании используются только неизменяемые значения. В Scala это означает:
- все переменные создаются как поля
val
- используются только неизменяемые классы коллекций, такие как
List
,Vector
и неизменяемые классыMap
иSet
Использование только неизменяемых переменных поднимает интересный вопрос: если все статично, как вообще что-то меняется?
Когда дело доходит до использования коллекций, один из ответов заключается в том,
что существующая коллекция не меняется;
вместо этого функция применяется к коллекции, чтобы создать новую.
Именно здесь вступают в действие функции высшего порядка, такие как map
и filter
.
Например, представим, что есть список имен в нижнем регистре — List[String]
,
и необходимо найти все имена, начинающиеся с буквы "j"
, чтобы затем сделать первые буквы заглавными.
В ФП код будет выглядеть так:
val a = List("jane", "jon", "mary", "joe")
// a: List[String] = List("jane", "jon", "mary", "joe")
val b = a.filter(_.startsWith("j")).map(_.capitalize)
// b: List[String] = List("Jane", "Jon", "Joe")
Как показано, исходный список a
не меняется.
Вместо этого к a
применяется функция фильтрации и преобразования, чтобы создать новую коллекцию,
и результат присваивается неизменяемой переменной b
.
Точно так же в ФП не используются классы с изменяемыми параметрами конструктора var
.
В ФП создание такого класса не привествуется:
class Person(var firstName: String, var lastName: String)
Вместо этого обычно создаются case class
-ы, чьи параметры конструктора по умолчанию неизменяемые (val
):
case class Person(firstName: String, lastName: String)
Теперь можно создать экземпляр Person
как поле val
:
val reginald = Person("Reginald", "Dwight")
// reginald: Person = Person(firstName = "Reginald", lastName = "Dwight")
Затем, при необходимости внести изменения в данные, используется метод copy
,
который поставляется с case class
-ом, чтобы "обновлять данные через создание копии", например:
val elton = reginald.copy(
firstName = "Elton",
lastName = "John"
)
// elton: Person = Person(firstName = "Elton", lastName = "John")
Существуют множество других приёмов работы с неизменяемыми коллекциями и переменными.
В зависимости от задач вместоcase class
-ов можно создаватьenum
-ы,trait
-ы или классы. Для более подробной информации См. главу "Моделирование данных".
Ссылки: