Clojure 如何使用宏迭代列表?
我试图通过调用REPL中的以下表达式来打印给定命名空间中所有函数的文档:Clojure 如何使用宏迭代列表?,clojure,Clojure,我试图通过调用REPL中的以下表达式来打印给定命名空间中所有函数的文档: (doseq [f (dir-fn 'clojure.repl)] (doc f)) 但是,调用此表达式将返回nil,而不将文档打印到REPL。我知道这可能与doc是一个宏有关,但我是一个Clojure新手,不完全确定如何理解这个问题 为什么此表达式在不打印文档的情况下返回nil 如何修改此表达式,使其打印给定命名空间中每个函数的文档 谢谢 更新:将两个答案结合起来: (defn ns-docs [ns']
(doseq
[f (dir-fn 'clojure.repl)]
(doc f))
但是,调用此表达式将返回nil
,而不将文档打印到REPL。我知道这可能与doc
是一个宏有关,但我是一个Clojure新手,不完全确定如何理解这个问题
nil
(defn ns-docs [ns']
(doseq [[symbol var] (ns-interns ns')]
(newline)
(println symbol)
(print " ")
(println (:doc (meta var)))))
(ns-docs 'clojure.repl)
我想从这里开始:
- (名称相似,但不同)
- API和参考部分位于
doc
位于命名空间clojure.repl
中,它反映了它的预期用途(由repl中的人使用)。下面是一些代码,它们也将在名称空间上迭代&打印文档字符串(使用不同的技术):
其中demo.core
是感兴趣的名称空间
请注意,ns实习生
为您提供了一个符号和变量,如:
fn-symbol => <#clojure.lang.Symbol -main>
fn-var => <#clojure.lang.Var #'demo.core/-main>
我想从这里开始:
- (名称相似,但不同)
- API和参考部分位于
doc
位于命名空间clojure.repl
中,它反映了它的预期用途(由repl中的人使用)。下面是一些代码,它们也将在名称空间上迭代&打印文档字符串(使用不同的技术):
其中demo.core
是感兴趣的名称空间
请注意,ns实习生
为您提供了一个符号和变量,如:
fn-symbol => <#clojure.lang.Symbol -main>
fn-var => <#clojure.lang.Var #'demo.core/-main>
为什么这个表达式在不打印文档的情况下返回nil
因为doc
宏正在从循环接收符号f
,而不是直接接收函数符号
如何修改此表达式,使其打印给定命名空间中每个函数的文档
然后,如果需要,可以打印这些贴图/字符串
为什么这个表达式在不打印文档的情况下返回nil
因为doc
宏正在从循环接收符号f
,而不是直接接收函数符号
如何修改此表达式,使其打印给定命名空间中每个函数的文档
然后,如果需要,您可以打印这些映射/字符串。虽然这可能无法帮助您回答问题,但在学习Clojure时,评估宏的问题会出现很多 宏负责评估其参数。在这种情况下,
clojure.repl/doc
将忽略当前的词法上下文,并假定您提供的符号f
是要查看文档的函数名。它这样做是因为它打算在REPL中使用,并且假设您不想一直键入引号
由于f
不存在,因此它不会打印任何内容。然后doseq
返回nil
,因为它的存在只是为了做一些副作用-因此从do
开始。为了将参数传递给拒绝这样尊重词法上下文的宏,需要为列表中的每个元素编写代码
您可以手动执行,也可以将代码构造为数据,并将其传递给eval
执行。您可以使用命令式风格,使用doseq
:
(doseq [f (ns-interns 'clojure.repl)]
(eval `(doc ~(symbol "clojure.repl" (str (first f))))))
或者以一种更接近Clojurey的方式(这将允许您通过从末尾删除eval
并在REPL处运行它来查看它将执行的代码):
在这两种方法中,我们都使用quote和syntax quote从名称空间反映的符号列表中构造一些代码,并将其传递给eval
,以实际执行它。应该为你指出正确的方向来理解这里发生的事情
这是一个不应该编写宏的例子,除非您没有其他选择。宏不构成,通常很难使用。进行更深入的讨论,都是很好的谈话 虽然这可能无助于回答您的问题,但在学习Clojure时,评估宏的问题经常出现 宏负责评估其参数。在这种情况下,
clojure.repl/doc
将忽略当前的词法上下文,并假定您提供的符号f
是要查看文档的函数名。它这样做是因为它打算在REPL中使用,并且假设您不想一直键入引号
由于f
不存在,因此它不会打印任何内容。然后doseq
返回nil
,因为它的存在只是为了做一些副作用-因此从do
开始。为了将参数传递给拒绝这样尊重词法上下文的宏,需要为列表中的每个元素编写代码
您可以手动执行,也可以将代码构造为数据,并将其传递给eval
执行。您可以使用命令式风格,使用doseq
:
(doseq [f (ns-interns 'clojure.repl)]
(eval `(doc ~(symbol "clojure.repl" (str (first f))))))
或者以一种更接近Clojurey的方式(这将允许您通过从末尾删除eval
并在REPL处运行它来查看它将执行的代码):
在这两种方法中,我们都使用quote和syntax quote从名称空间反映的符号列表中构造一些代码,并将其传递给eval
,以实际执行它。应该为你指出正确的方向来理解这里发生的事情
这是一个不应该编写宏的例子,除非您没有其他选择。宏
(doseq [f (ns-interns 'clojure.repl)]
(eval `(doc ~(symbol "clojure.repl" (str (first f))))))
(->> (ns-interns 'clojure.repl)
(map #(list 'clojure.repl/doc (symbol "clojure.repl" (str (first %)))))
(cons `do)
eval)