Функциональное программирование: состояние против переназначения

голоса
13

Мне нужна помощь в получении моей головы вокруг разницы между моей нынешней ООП понятием государства, и как это будет сделано в функциональном языке, как Haskell или Clojure.

Чтобы использовать банальный пример, предположим, что мы имеем дело с объектами счета упрощенным банка / / независимо структур. В языке ООП, я должен был бы некоторый класс держит ссылку на BankAccount, который будет иметь переменный экземпляр для вещей, как процентные ставки, и методы, такие как setInterestRate (), которые изменяют состояние объекта и, как правили не возвращают ничего. В Clojure сказать, что я быть_наст банк-счет-структура (прославленная HashMap), а также специальные функции, которые принимают параметр банка-счет и другую информацию, и возвращаю новую структуру. Таким образом, вместо того чтобы изменить состояние исходного объекта, теперь у меня есть новый один возвращается с желаемыми изменениями.

Итак ... что же мне делать с ним? Переписать все, что переменная ссылается на старый банк-счет? Если да, то, что имеет преимущества по сравнению с государством меняется объектный подход? В конце концов, в обоих случаях, кажется, один имеет переменную, которая ссылается на объект с необходимыми изменениями. Отставание, как я, у меня есть только смутное представление о том, что происходит.

Я надеюсь, что имело смысл, спасибо за любую помощь!

Задан 09/12/2008 в 20:24
источник пользователем
На других языках...                            


4 ответов

голоса
11

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

Аналогия будет пространство-время в физике. Если рассматривать мир как 3D, то объекты не имеют фиксированные позиции - они перемещаются с течением времени. Для того, чтобы привести математику, чтобы нести на физическом мире, поэтому мы добавим измерение времени и рассмотрим значение различных свойств в определенное время. При этом, мы сделали объекты нашего исследования в константы. Точно так же, в программировании, есть концептуальная простота, которая будет иметься, работая с непреложными ценностями. Объекты с идентичностью в реальном мире может быть смоделированы как последовательность неизменных значений (состояния объекта при увеличении времени), а не как единое значение, которое изменяется.

Конечно , подробности о том , как связать последовательность значений к «идентичности объекта» могут быть немного волосатыми. Haskell имеет Монады , которые позволяют вам состояние модели. Функциональное программирование Реактивного является более буквальной попыткой моделирования объектов в мире с чисто функциональными обновлениями, что я думаю , что это очень перспективное направление для программирования.

Отмечу, что Clojure, в отличие от Haskell, не является чистым, и вы можете обновить переменные, как вы предложили. Если вы только обновит несколько переменных на высоком уровне, вы все еще будете, вероятно, пользуются многие концептуальные простоты преимущества функционального программирования.

Ответил 09/12/2008 в 21:10
источник пользователем

голоса
8

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

updatePortfolio :: Request -> Portfolio -> Portfolio

И ваш главный цикл может считывать запросы со стандартного ввода и сохранить свой портфель до настоящего времени. (В качестве примера не много пользы, если вы не можете писать портфель, а также, но это проще.)

readRequest :: IO Request  -- an action that, when performed, reads a Request with side effects

main :: Portfolio -> IO ()  -- a completely useless program that updates a Portfolio in response to a stream of Requests

main portfolio = do req <- readRequest
                    main (updatePortfolio req)

и теперь я надеюсь, что вы видите, что случилось с вашим изменяемым состоянием: в типичной функциональной программе, утверждает, что изменения передаются в качестве параметра функции. Когда состояние changess, вы делаете новый вызов функции. Вызов находится в хвостовой позиции (вы можете посмотреть «правильное хвост вызова»), и поэтому он не использует какие-либо дополнительные ресурсы, а на самом деле, когда компилятор генерирует код сборки он генерирует цикл, и он будет держать указатель на постоянно меняющийся портфель в реестре.

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

Ответил 10/12/2008 в 04:57
источник пользователем

голоса
4

Итак ... что же мне делать с ним? Переписать все, что переменная ссылается на старый банк-счет?

да

Если да, то, что имеет преимущества по сравнению с государством меняется объектный подход?

Скажем, вычисление любых действий, которые вы делаете на этой структуру занимает много времени и что-то происходит на полпути, и вам нужно вернуться к исходному структуре или вычисление появлялось сообщение об ошибке. С интерпретацией вы представили мне в OO (используя ссылку, потому что вы можете иметь неизменный язык OO), что данные могут быть неизвестны коррумпированными --О, если только достаточно информации, не была дана от вызова функции неисправного, и позволяет предположить, что не удалось плохо. В функциональном подходе вы знаете наверняка, что ваша первоначальная структура данных является правильным --because вы изначально сделали копию.

Продлить этот сценарий в многопоточных приложениях. Мы можем гарантировать, что никто больше не использует структуру данных, которые мы так как все мы имеем нашу собственную версию.

Кроме того, мы можем сэкономить пространство, используя данные из другой структуры, которые мы копирование с. Классическим примером является при добавлении элемента к голове списка. Если у нас есть указатель на второй элемент, а указатель на первый элемент можно ссылаться как списки только от размера первого (см. Ниже) Без неизменности мы не можем гарантировать это.

        b__
           |  
a -> [6|] -+-> [5|] -> [4|] -> [3|] -> [2|] -> [1|x]
Ответил 09/12/2008 в 20:58
источник пользователем

голоса
1

Посмотрите на Haskell, который является чисто функциональным языком, он не имеет переназначения бы то ни было, а также никаких других побочные эффектов: для того , чтобы сделать IO, в IO монады построить это фактически заменяет RealWorld с новым экземпляром мир , который имеет, например, новый текст , отображаемый в консоли.

Ответил 09/12/2008 в 22:29
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more