Scala 3 — Book

Неизменяемые значения

Language

В чистом функциональном программировании используются только неизменяемые значения. В Scala это означает:

  • все переменные создаются как поля val
  • используются только неизменяемые классы коллекций, такие как List, Vector и неизменяемые классы Map и Set

Использование только неизменяемых переменных поднимает интересный вопрос: если все статично, как вообще что-то меняется?

Когда дело доходит до использования коллекций, один из ответов заключается в том, что существующая коллекция не меняется; вместо этого функция применяется к коллекции, чтобы создать новую. Именно здесь вступают в действие функции высшего порядка, такие как map и filter.

Например, представим, что есть список имен в нижнем регистре — List[String], и необходимо найти все имена, начинающиеся с буквы "j", чтобы затем сделать первые буквы заглавными. В ФП код будет выглядеть так:

val a = List("jane", "jon", "mary", "joe")
val b = a.filter(_.startsWith("j"))
         .map(_.capitalize)

Как показано, исходный список a не меняется. Вместо этого к a применяется функция фильтрации и преобразования, чтобы создать новую коллекцию, и результат присваивается неизменяемой переменной b.

Точно так же в ФП не используются классы с изменяемыми параметрами конструктора var. В ФП создание такого класса не привествуется:

// не стоит этого делать в ФП
class Person(var firstName: String, var lastName: String)
             ---                    ---

Вместо этого обычно создаются case классы, чьи параметры конструктора по умолчанию неизменяемые (val):

case class Person(firstName: String, lastName: String)

Теперь можно создать экземпляр Person как поле val:

val reginald = Person("Reginald", "Dwight")

Затем, при необходимости внести изменения в данные, используется метод copy, который поставляется с case классом, чтобы “обновлять данные через создание копии”, например так:

val elton = reginald.copy(
  firstName = "Elton",   // обновить имя
  lastName = "John"      // обновить фамилию
)

Существуют множество других приёмов работы с неизменяемыми коллекциями и переменными.

В зависимости от задач вместо case классов можно создавать перечисления, trait-ы или классы. Для более подробной информации см. главу “Моделирование данных”.

Contributors to this page: