我不明白 (doc fn)...它说我可以命名一个函数,但我不能通过它的名字调用它?

I don't understand the (doc fn)...it says I can name a function, but I can't invoke it by its name?

我是 Clojure 的新手,正在努力理解这些概念。 REPL 帮助我获得了 "stuff" 的文档。所以我想定义一个函数...

clojure-noob.core> (doc fn)
-------------------------
clojure.core/fn
  (fn name? [params*] exprs*)
  (fn name? ([params*] exprs*) +)
Special Form
  ...
  name => symbol

...文档建议我可以命名我的函数。 REPL 接受了我的函数,但我无法调用它,"Unable to resolve symbol.."...

clojure-noob.core> (fn add-pair [a b] (+ a b))
#<core$eval3364$add_pair__3365 clojure_noob.core$eval3364$add_pair__3365@6fb5a33b>
clojure-noob.core> (add-pair 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: add-pair in this context, compiling:(/private/var/folders/1g/fnytl2x93sx6hp2f1rsf4h1r5xtqv_/T/form-init6828995349142227131.clj:1:1) 
clojure-noob.core> 

省略名称并构建适当的 fn def 确实可以完成工作,就像利用 defn 宏一样...

clojure-noob.core> (def another-add-pair (fn [a b] (+ a b)))
clojure-noob.core> (another-add-pair 1 2)
3
clojure-noob.core> (defn yet-another-add-pair [a b] (+ a b))
#'clojure-noob.core/yet-another-add-pair
clojure-noob.core> (yet-another-add-pair 3 4)
7

(doc fn) 的输出显然有一些我不理解的地方。特别是,那里的 name? 是什么,您可以用它做什么?我同样在努力学习如何阅读文档以及理解 fn 特殊形式。谢谢。

从 REPL 调用 (fn add-pair [a b] (+ a b)) 构建该函数的实例,然后将其打印到屏幕上。之后它就消失了并且 没有保存在任何地方 。这就是为什么您无法使用 doc 函数获取它的文档的原因。 fn 文字中的 name 参数通常用于进行递归调用,并不意味着它会在任何地方以该名称保存。

如果你调用 (defn add-pair [a b] (+ a b)) 然后它 将函数保存到命名空间 然后 doc 函数可以稍后查找并打印它文档字符串。

  • A fn 表单计算为 函数对象

  • 您可以立即应用函数对象:

    ((fn [a b] (+ a b)) 1 1) ;=> 2

  • 如果要在本地引用函数对象,请使用 let 绑定:

    (let [add-pair (fn [a b] (+ a b))] (add-pair 1 1)) ;=> 2

  • 一个函数对象是一个值1[3 :a]:

    (let [double (fn [n] (* 2 n))] (({double (comp double double)} double) 3) ;=> 12

  • let 绑定在 fn 表单中不存在 - 您需要一个 名称参数:

    ((fn fact [n] (case n, 0 1, (* n (fact (dec n))))) 5) ;=> 120

  • letfn 两者兼顾:

    (letfn [(fact [n] (case n, 0 1, (* n (fact (dec n)))))] (fact 5)) ;=> 120

  • 如果您希望该函数可以全局访问,请将其绑定到 var 使用 def:

    (def fact (fn fact [n] (case n, 0 1, (* n (fact (dec n))))))

    (fact 5) ;=> 120

  • defn宏更简洁地做同样的事情:

    (defn fact [n] (case n, 0 1, (* n (fact (dec n)))))

    (fact 5) ;=> 120