2017-01-16 3 views
2

Есть ли возможность присвоить значение символу в Clojure, а затем переназначить тот же символ? Сейчас я вижу, что все переменные в Clojure постоянны. Это правильно?Все переменные в Clojure постоянны?

+0

Если бы сказал, что это Clojure! Вы должны указать, что вы имеете в виду. В, скажем, 'let' binding, вы можете создать' a' со значением 1, использовать его, а затем изменить значение на 2. Любой, кто использовал 'a' до изменения, по-прежнему будет видеть 1.' def' s может также изменить их значение, хотя редко это всегда что-то, что вы хотите сделать. – Carcigenicate

+0

Моя терминология была неверна, ответ здесь правильный. Shadowing выглядит как переназначение, но на самом деле это новое значение. – Carcigenicate

ответ

5
  • Местные имена могут отскакивать:
  • (Global) символы могут быть переопределен.
  • Есть несколько разновидностей вещи, которые (как правило) символ может быть обязан содержание которых является изменяемым:

Эти последние e имеют разные характеристики и цели.

От the above:

Примечание - Вы не можете назначить для работы Params или локальных привязок. Только Java-поля, Vars, Refs и Agents могут быть изменены в Clojure.

Пример подменой местное название:

(let [coll (range) 
     coll (rest coll) 
     coll (filter odd? coll) 
     coll (take 5 coll)] 
    coll) 
;(1 3 5 7 9) 
+0

Можете ли вы привести пример кода локальных имен, которые можно отскочить? – CrazySynthax

+0

... любое использование 'recur' с аргументами также переименовывает имена. –

+1

'let' в Clojure как' let * 'в других языках lisp. Каждый 'coll', который вы делаете, является новым связыванием, которое затеняет старый и не восстанавливает первоначальную привязку. В качестве примера этого представьте это '(let [f (range) f (fn [] (first f))] (f))' '' f ', зафиксированное в закрытии, является тем, что функция получает одно и то же имя и оба существуют. – Sylwester

2

Все локальные переменные - let -bound или fn -bound (fn параметров) - являются постоянными, это верно. (Они похожи на математические переменные, поскольку вы можете оценивать выражения, которые они задействуют при различных присвоениях значениям переменным, но при любой такой оценке присвоенное значение должно быть постоянным.)

Обратите внимание, что такие местные жители могут be затененных идентично названными местными жителями во вложенных областях; теневые локали могут иметь независимые значения, но они также не могут быть переназначены.

Существует также отличная концепция Vars - объектов верхнего уровня, наиболее часто вводимых формами def. Они могут вернуть свои корневые значения, и, кроме того, если они отмечены :dynamic, можно отменить нить-локально.

+0

Итак, можем ли мы согласиться с тем, что ответ на мой вопрос «да»? что все переменные в Clojure постоянны? – CrazySynthax

+0

@CrazySynthax, eh. атомы и рефлексы не являются постоянными, а вары - только со-константы (они могут * быть отскок, хотя это хорошая практика только во время разработки, а не в производстве). И это не единственные ссылочные типы - у вас также есть агенты и фьючерсы. Clojure имеет значительный набор инструментов для работы со сменой состояния во времени, даже если правильный способ взаимодействия с этим состоянием - это восстановление новых значений, а не изменение вещей на месте. –

+0

Незначительная точка: вы можете затенять локальную область в * той же * '' '' 'или' fn' scope: '((fn [n n] n) 3 5)' => '5'. Наверное, более запутанным, чем его ценность. – Thumbnail