当前位置: 动力学知识库 > 问答 > 编程问答 >

design - Why does Clojure's for macro only accept one body expression?

问题描述:

Clojure's for macro accepts two arguments: a sequence of binding forms, and a body expression. As such, if I want to do multiple things in the loop, I have to wrap multiple expressions in a do block to make them a single expression.

Compare:

(doseq [a (range 3)]

(prn 'a a)

(inc a))

to:

(for [a (range 3)]

(prn 'a a)

(inc a))

The doseq works as expected. The for complains:

clojure.lang.ArityException: Wrong number of args (3) passed to: core/for

My question is, why doesn't this work? Why didn't the designer(s) of Clojure allow multiple "body" expressions in the for loop, like they did in doseq and when? It's not as if there is any semantic ambiguity, right?

网友答案:

Clojure's for is not a loop, it is lazy list comprehension. Since only the value of last expression in the body of a (implicit) do is returned, any other expressions would have to exist merely for side effects. Execution for side-effects is the job of doseq, which is why it has an implicit do. That for does not should be a reminder, do you really want side effects in your lazy sequence? Though there are legitimate reasons for doing so, care is warranted that those side effects execute when you want.

(def foo (for [a (range 32)]
           (do
             (prn (str "a is " a))
             (inc a))))

(take 1 foo)
;=>
  ("a is 0"
   "a is 1"
   ...
  "a is 31"
  1) ; <= the return value

(take 10 foo)
;=>
  (1 2 3 4 5 6 7 8 9 10) ; aw, no side effects this time
分享给朋友:
您可能感兴趣的文章:
随机阅读: