首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clojure中的fn和defn有什么区别?

clojure中的fn和defn有什么区别?
EN

Stack Overflow用户
提问于 2018-03-09 01:35:04
回答 2查看 2.7K关注 0票数 9

以下是两种在Clojure中编写函数的方法:

代码语言:javascript
复制
(defn foo [a b] (+ a b))
(fn foo [a b] (+ a b))

我可以这样称呼他们:

在“defn”一案中

代码语言:javascript
复制
(foo 1 2)

在“fn”的情况下

代码语言:javascript
复制
((fn foo [a b] (+ a b)) 1 2)

‘'fn’似乎没有将其可选名称插入到当前范围中,而'defn‘似乎正是这样做的。有其他的区别或理由有两种方法来创建函数吗?我们为什么不像这样使用“fn”呢?

代码语言:javascript
复制
(fn foo [a b] (+ a b))
(foo 1 2)
EN

Stack Overflow用户

回答已采纳

发布于 2018-03-09 01:42:31

defn基本上被定义为*

代码语言:javascript
复制
(defmacro defn [name args & body]
  `(def ~name (fn ~args ~@body)))

或者换句话说,你基本上可以写:

代码语言:javascript
复制
(defn my-func [a]
  (stuff a))

作为*

代码语言:javascript
复制
(def my-func
  (fn [a] (stuff a)))

只要使用fn,就会创建一个匿名函数,它不会单独绑定到任何外部符号。必须使用letdef将其绑定到外部。

通过用deffn定义def,可以分离将函数绑定到符号(以及随之而来的所有其他复杂性)和处理函数行为的响应。

当您为fn提供名称时,不能在函数之外引用它,但是可以使用它来引用自身来创建递归的匿名函数:

代码语言:javascript
复制
(fn my-func [n] (my-func (inc n))

而且,它为函数提供了一个稍微好一些的名称,可以在堆栈跟踪中显示,以便于调试:

代码语言:javascript
复制
(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的基本内核可能有点让人望而生畏。

票数 18
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49185304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档