Когда можно использовать var в Scala?

Я знаю, что в Scala есть var (для изменяемого состояния), но чистое функциональное программирование не одобряет использование любого изменяемого состояния и скорее фокусируется на использовании val для всего.

Исходя из императивного мира, трудно отказаться от изменчивого состояния.

Мой вопрос: когда можно использовать var в вашем коде Scala? Действительно ли весь код можно выполнить, используя только val. Если да, то почему в Scala есть переменные?


person Soumya Simanta    schedule 27.10.2012    source источник
comment
Я полагаю, вы хотите спросить, почему в Scala есть vars.   -  person pedrofurla    schedule 27.10.2012
comment
@pst - Вы правы, Scala не чиста. Я думаю, это одна из причин, почему у него есть вары. Тем не менее, мой первоначальный вопрос все еще остается.   -  person Soumya Simanta    schedule 27.10.2012


Ответы (2)


Вот несколько причин для vars в Scala:

  • Scala — мультипарадигмальный язык, он поощряет функциональное программирование, но оставляет выбор за программистом.
  • Совместимость. Многие API-интерфейсы Java предоставляют изменяемые переменные.
  • Производительность: иногда использование var дает вам наилучшую возможную производительность.
  • Когда люди говорят, что все можно сделать без переменных, это правильно в том смысле, что Scala по-прежнему будет завершена по Тьюрингу без переменных. Однако это ничего не меняет в справедливости предыдущих пунктов.
person Kim Stebel    schedule 27.10.2012
comment
Спасибо за отличный ответ. Но не могли бы вы дать нам ссылку на Scala would still be turing complete without vars. - person Vishrant; 12.07.2018
comment
Я только что столкнулся с примером, в котором var имело смысл: мне нужно было написать обычную функцию, которая складывает некоторые целые числа в битовую маску. Я создал функцию, которая создавала аккумулятор переменных, а затем при определенных условиях добавляла значения в эту переменную, а затем возвращала окончательный результат. Переменная не подвергается никакому другому коду, инкапсулированному в одну функцию. Это можно переписать, чтобы использовать val, однако для каждого случая, когда требуется добавление к исходному var, вам нужно будет создать новый val, чтобы добавить к нему оператор return. Использование val здесь увеличило бы использование накладных расходов памяти ради неизменности... - person Rimer; 25.03.2020

Даже с точки зрения функционального программирования вы можете использовать переменные (или изменяемые объекты) локально, если они не покидают область, в которой они определены.

Например, рассмотрим эту (надуманную) функцию, которая возвращает размер списка:

def dumbSize( lst: List[Int] ): Int = {
   var i = 0
   var rest = lst
   while( rest != Nil ) {
     i += 1
     rest = rest.tail
   }
   i
}

Хотя эта (уродливая) функция использует vars, она по-прежнему чиста (нет побочных эффектов и всегда будет возвращать один и тот же результат для заданного значения аргумента).

Другим примером «инкапсуляции изменяемого состояния» является модель актора, в которой состояние актора часто является изменчивым.

person paradigmatic    schedule 27.10.2012
comment
Я думаю, вы имели в виду rest.tail - person Kim Stebel; 27.10.2012
comment
и замените последний rest на i - person Kim Stebel; 27.10.2012
comment
Кроме того, вы должны заменить rest.size > 0 на rest != Nil, чтобы не иметь квадратичную производительность. - person Kim Stebel; 27.10.2012
comment
или это было просто для того, чтобы продемонстрировать ошибочность императивного программирования? ;) - person Kim Stebel; 27.10.2012
comment
@KimStebel Я отладил это, спасибо. Я просто хотел проиллюстрировать, как функция может оставаться чистой, используя неизменяемый (подверженный ошибкам) ​​код. - person paradigmatic; 27.10.2012
comment
@KimStebel Я действительно поражен количеством ошибок, которые мне удалось запихнуть в эту маленькую функцию! Спасибо за исправление. - person paradigmatic; 27.10.2012
comment
я тоже сначала заметила баги а потом увидела там твое имя и подумала неужели??? - person Kim Stebel; 27.10.2012