简体   繁体   English

Clojure循环形式如何工作?

[英]How does Clojure loop form works?

I am new to Clojure an Functional Programming both. 我是Clojure和功能编程的新手。 I tried my best, understanding the loop construct. 我尽我所能,理解循环结构。

I can use it, I can look at a code written with it and tell the output but what I dont understand is,How does it work ? 我可以使用它,我可以查看用它编写的代码并告诉输出但我不明白的是,它是如何工作的?

is it same as writing an anonymous function with parameters and then keeping recur at the tail with same arity and new values ? 是否与使用参数编写匿名函数然后使用相同的arity和new值保持重复?

is it an inbuilt macro or something for it ? 它是一个内置的宏还是它的东西?

Actually, loop is not a function or a macro. 实际上, loop不是函数或宏。 It is a special form . 这是一种特殊的形式 It works just like let (which is also a special form) except that it acts as a target for recur . 它的工作原理就像let (它也是一种特殊的形式),除了它作为recur的目标。

One way to differentiate functions, macros, and special forms is to examine how their arguments are evaluated: 区分函数,宏和特殊形式的一种方法是检查其参数的计算方式:

  • Function arguments are always evaluated, and then the results are passed to the function. 始终计算函数参数,然后将结果传递给函数。
  • Macro arguments are not evaluated until the macro expands to a new unevaluated form. 在宏扩展为新的未评估表单之前,不会评估宏参数。
  • Special form arguments are not evaluated when passed, but the special form may or may not choose to evaluate them internally. 传递时不评估特殊形式参数,但特殊形式可能会或可能不会选择在内部对它们进行评估。

dbyrne 's answer is all true, and good, but I'd like to address your further question "Is it the same as writing an anonymous function with parameters and then recur at the tail with same arity and new values?". dbyrne的答案都是正确的,而且很好,但是我想解决你的另一个问题“它是否与用参数编写一个匿名函数然后在尾部recur相同的arity和new值?”。 Yes, it is exactly like that: 是的,它完全是这样的:

(loop [x 1, y 2]
  (if (whatever x y)
    (recur (inc x) (dec y))
    (* x y)))

is functionally identical to 在功能上是相同的

((fn [x y]
   (if (whatever x y)
     (recur (inc x) (dec y))
     (* x y)))
 1 2)

If loop didn't exist, you could write it as a simple macro that emits this sort of form, but the compiler has a special loop form which is faster. 如果loop不存在,您可以将其编写为发出此类形式的简单宏,但编译器具有更快的特殊loop形式。

(defmacro loop [bindings & body]
  (let [bindings (partition 2 bindings)]
    `((fn [~@(map first bindings)]
        (do ~@body))
      ~@(map second bindings))))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM