以下是两种在Clojure中编写函数的方法:
(defn foo [a b] (+ a b))
(fn foo [a b] (+ a b))我可以这样称呼他们:
在“defn”一案中
(foo 1 2)在“fn”的情况下
((fn foo [a b] (+ a b)) 1 2)‘'fn’似乎没有将其可选名称插入到当前范围中,而'defn‘似乎正是这样做的。有其他的区别或理由有两种方法来创建函数吗?我们为什么不像这样使用“fn”呢?
(fn foo [a b] (+ a b))
(foo 1 2)发布于 2018-03-09 01:42:31
defn基本上被定义为*
(defmacro defn [name args & body]
`(def ~name (fn ~args ~@body)))或者换句话说,你基本上可以写:
(defn my-func [a]
(stuff a))作为*
(def my-func
(fn [a] (stuff a)))只要使用fn,就会创建一个匿名函数,它不会单独绑定到任何外部符号。必须使用let或def将其绑定到外部。
通过用def和fn定义def,可以分离将函数绑定到符号(以及随之而来的所有其他复杂性)和处理函数行为的响应。
当您为fn提供名称时,不能在函数之外引用它,但是可以使用它来引用自身来创建递归的匿名函数:
(fn my-func [n] (my-func (inc n))而且,它为函数提供了一个稍微好一些的名称,可以在堆栈跟踪中显示,以便于调试:
(defn my-func []
((fn my-inner-func [] (/ 1 0))))
=> #'digital-rain.core/my-func
(my-func)
java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide(Numbers.java:158)
at clojure.lang.Numbers.divide(Numbers.java:3808)
at digital_rain.core$my_func$my_inner_func__2320.invoke(form-init1838550899342340522.clj:2)
at digital_rain.core$my_func.invokeStatic(form-init1838550899342340522.clj:2)
at digital_rain.core$my_func.invoke(form-init1838550899342340522.clj:1)*这些都是粗俗的轻描淡写和有点误导,但他们简化了事情。
实际上,defn不是使用defmacro定义的;defmacro实际上是使用defn定义的。defn还添加了一些很好的东西,如前/后条件检查、文档和其他元信息;但这与此无关。我建议您查看一下它的来源,以获得更深入的了解;尽管它非常复杂。clojure.core的基本内核可能有点让人望而生畏。
https://stackoverflow.com/questions/49185304
复制相似问题