【问题标题】:purpose of defn in ClojureClojure 中 defn 的用途
【发布时间】:2013-07-25 14:42:04
【问题描述】:

我对 defn 的作用有点疑惑。如果 fn 只生成匿名函数,我可以理解需要一个结合了 def 和 fn 功能的构造,但 fn 也可以创建命名函数。至少在 repl 中,我看不出这种用法与 defn 有何不同。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    当您向fn 提供名称符号时,它仅在函数定义内绑定到函数对象本身。这是为了允许匿名函数调用自己 (Clojure - special forms)。

    因此,要创建一个将fn 绑定到全局可访问名称的函数,您必须使用

    (def somename 
        (fn ...body...
    

    defn 只是一个捷径。

    (defn somename 
        ...body...
    

    回复您的评论,来自一个新的回复:

    Give me some Clojure:
    > (fn foo [] (+ 1 3))
    #<sandbox31764$eval31779$foo__31780 sandbox31764$eval31779$foo__31780@12eae8eb>
    > (foo)
    java.lang.RuntimeException: Unable to resolve symbol: foo in this context
    > (defn foo [] (+ 1 3))
    #'sandbox31764/foo
    > (foo)
    4
    >  
    

    如您所见,我无法调用用fn 创建的foo 函数,因为它没有绑定到Var。

    【讨论】:

    • 同样的问题如下:如果 fn 名称符号是内部绑定的,为什么我可以从 repl 中调用它?
    • 也许已经有一个同名的 Var?您是否尝试过重置您的repl?我无法重现您描述的行为。
    • @Planarian 请将您输入的代码发布到新的 REPL 中,以便获得您描述的行为。
    • 你是对的。我清除了我的会话,重新加载了函数,并得到了一个错误(如你所料)。我没有故意定义一个 var,所以它有点神秘......
    【解决方案2】:

    主要区别在于defn 创建一个全局名称,而fn 只创建一个词法名称。全局名称也是一个 var,因为它最终是用 def 创建的。您可以给匿名函数的名称不是 var,并且仅在该函数的范围内。这主要是因为函数可以递归。

    【讨论】:

    • 但是如果fn创建的名字的作用域是函数内部的,为什么我可以从repl调用呢?
    • 你不能。 (fn bingo [] (println "bingo"))
    猜你喜欢
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多