Существуют ли переменные в понимании последовательности Clojure?

Я читаю Programming Clojure 2nd edition, и на странице 49 он описывает конструкцию цикла for Clojure, которая, по его словам, на самом деле является пониманием последовательности.

Авторы предлагают следующий код:

(defn indexed [coll] (map-indexed vector coll))

(defn index-filter [pred col]
  (when pred
    (for [[idx elt] (indexed col) :when (pred elt)] idx)))

(index-filter #{\a} "aba")
(0 2)

... предпочтительнее императивного примера на основе Java, и приведено свидетельство того, что он «с помощью функций более высокого порядка ... функциональный индекс любого избегает необходимости в переменных».

Что такое «idx», «elt», если они не являются переменными? Имеются ли в виду переменные помимо аккумуляторов?

Кроме того, почему # {\ a} вместо «a»?


person Allyl Isocyanate    schedule 26.09.2012    source источник


Ответы (2)


  1. В функциональных языках нет переменных. На самом деле вам нужно различать переменную и значение. idx это просто имя, привязанное к конкретному значению, и вы не можете его переназначить (но вы можете переназначить его другому значению).

  2. Первым параметром функции index-filter является предикат, то есть функция, возвращающая true или false. #{\a} это структура данных set, но с ней также можно обращаться как с функцией. Если вы передаете элемент в качестве аргумента функции set, она возвращает этот аргумент (например, true), если элемент существует, и nil (например, false) в противном случае. Таким образом, вы можете думать об этом предикате set как об анонимной функции, написанной более понятным способом #(contains? #{\a} %)

person mishadoff    schedule 26.09.2012
comment
Поэтому ранее в главе обсуждались переменные, то есть (def a 1). Я предполагаю, что меня смущает разница между переменной и неизменной переменной, значение которой изменяется. Действительно ли это создает idx1, idx2, idx3 и т. д. в памяти для каждой итерации, и когда idx разыменовывается, он возвращает последнее значение idx? - person Allyl Isocyanate; 27.09.2012
comment
вы просто не можете изменить связанное значение в области, где оно определено. так, например, каждая ваша итерация for имеет точное значение idx, и вы не можете просто переназначить его, как в императивных языках. - person mishadoff; 27.09.2012
comment
Переменные — это фактические ячейки памяти, содержимое которых можно читать и записывать. Привязки в понимании списка, как и в выражении (let [] ...), носят более лексический характер — вы можете думать о символах здесь как о заполнителях, которые заменяются фактическим значением при оценке выражения. - person Alex; 27.09.2012
comment
Все еще не понимаю этого. Если его A. именованный указатель на место в памяти, B. имеет значение, а C. динамически изменяется... как это не переменная? Если они действительно неизменны, то я бы подумал, что все они будут отдельными местами в памяти (и там нужно как-то собирать мусор) - person Allyl Isocyanate; 28.09.2012

pred — это функция, а #{\a} — это набор, содержащий символ a. В Clojure набор — это функция, которая возвращает true, если ее аргумент \a содержится в ней. Вы также можете использовать #(= % \a) или (fn [x] (= \a x)).

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

person JohnJ    schedule 26.09.2012