Clojure не использует переменные, как вы столкнулись в императивных языках, поэтому заявления типа (включая й) возвращает новое значение один выше чем x, оставляя x только вместо того, чтобы менять x на место.
Как написал этот код означает:
(defn print-questions [questions]
(let [number 0]
;; start with zero every time
;; don't carry any information forward between iterations of the loop
(doseq [question questions]
(println question)
(let [x (read-line)]
(if (= (.toLowerCase x) "y")
(inc number) ;; this DOES NOT change the value in number
(println "No"))))
number)) ;; when you are all done, return the original value of number
Это отлично подходит для случаев, когда множество потоков, работающих на тех же данных, хотя это и приводит к несколько иной взгляд на вещи.
Один из способов, чтобы написать что-то очень похожее было бы перебрать вопросы во время прохождения текущего значения числа от каждой итерации к следующей, как так:
user=> (defn print-questions [questions]
#_=> (loop [number 0 remaining-questions questions]
#_=> (println remaining-questions)
#_=> (if (seq remaining-questions)
#_=> (let [x (read-line)]
#_=> (if (= x "y")
#_=> (do (println "yes")
#_=> (recur (inc number) (rest remaining-questions)))
#_=> (do (println "No")
#_=> (recur number (rest remaining-questions)))))
#_=> number)))
#'user/print-questions
user=> (print-questions ["who" "what" "when" "why"])
[who what when why]
y
yes
(what when why)
y
yes
(when why)
n
No
(why)
y
yes
()
3
, который работает, хотя это немного многословным. Если вместо того, чтобы смотреть на это, как сокращение набора вопросов в ряд, где каждый этап сокращения добавляет либо один из нуля до результата, это немного более компактное:
user=> (defn print-questions [questions]
#_=> (reduce (fn [answer question]
#_=> (println question)
#_=> (if (= "y" (read-line))
#_=> (inc answer)
#_=> answer))
#_=> 0
#_=> questions))
#'user/print-questions
user=> (print-questions ["who" "what" "when" "why"])
who
y
what
n
when
y
why
y
3
уменьшить принимает функцию, чтобы сделать фактическую работу, значение для начала и список входов. Затем он использует эту функцию с первым значением для создания нового результата, затем использует функцию со вторым значением для получения нового результата, а третий и т. Д., Пока каждое значение на входе не сможет повлиять на конечный результат.
'(inc number)' больше напоминает 'number + 1'. Значение if похоже на '(x.toLowerCase(). Equals (" y ")? Число + 1: System.out.println (" Нет "))' – Sylwester