Переопределение let'd переменной в цикле Clojure

Согласно приложению Character Map, которое поставляется с Windows, значения Unicode для фигурных кавычек равны 0x201c и 0x201d. Замените эти значения прямой кавычкой 0x0022, и все будет хорошо.

String.Replace(0x201c, '"');
String.Replace(0x201d, '"');
36
задан MBCook 2 June 2009 в 17:05
поделиться

2 ответа

def определяет переменную верхнего уровня, даже если вы используете ее в функции или внутреннем цикле некоторого кода. То, что вы получаете в let , не является vars. Согласно документации для let :

Локальные переменные, созданные с помощью let, не являются переменными. После создания их значения никогда не изменяются!

(Акцент не мой.) Здесь вам не нужно изменять состояние для вашего примера; вы можете использовать loop и recur .

(loop [x 128]
  (when (> x 1)
    (println x)
    (recur (/ x 2))))

Если вы хотите проявить фантазию, вы можете полностью избежать явного цикла .

(let [xs (take-while #(> % 1) (iterate #(/ % 2) 128))]
  (doseq [x xs] (println x)))

Если вы действительно хотел использовать изменяемое состояние, атом мог бы работать.

(let [x (atom 128)]
  (while (> @x 1)
    (println @x)
    (swap! x #(/ %1 2))))

(Вам не нужен do ; , в то время как обертывает свое тело в явный для вас.) Если вы действительно, на самом деле хотел сделать это с помощью vars , вам придется сделать что-то ужасное, вроде этого.

(with-local-vars [x 128]
  (while (> (var-get x) 1)
    (println (var-get x))
    (var-set x (/ (var-get x) 2))))

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

50
ответ дан 27 November 2019 в 05:45
поделиться

Вары (это то, что вы получаете, когда вы "определяете" что-то) не предназначены для переназначения (но могут быть):

user=> (def k 1)
#'user/k
user=> k
1

Ничто не мешает вам делать:

user=> (def k 2)
#'user/k
user=> k
2

Если вам нужно локально настраиваемое «место» потока, вы можете использовать «привязку» и «установить!»:

user=> (def j) ; this var is still unbound (no value)
#'user/j
user=> j
java.lang.IllegalStateException: Var user/j is unbound. (NO_SOURCE_FILE:0)
user=> (binding [j 0] j)
0

Итак, вы можете написать такой цикл:

user=> (binding [j 0]
         (while (< j 10)
           (println j)
           (set! j (inc j))))
0
1
2
3
4
5
6
7
8
9
nil

Но я думаю, что это довольно унидиоматично.

13
ответ дан 27 November 2019 в 05:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: