Clojure函数和线程宏
我对Clojure语言还很陌生 在阅读时,我发现示例Clojure函数和线程宏,clojure,Clojure,我对Clojure语言还很陌生 在阅读时,我发现示例#([%])。因此,我尝试如下使用它: (def test1 #([%])) (test1 5) (def test1 #(-> [%])) (test1 5) 因此,我得到以下错误: ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:429) 它似乎在试图调用我想要返回
#([%])
。因此,我尝试如下使用它:
(def test1 #([%]))
(test1 5)
(def test1 #(-> [%]))
(test1 5)
因此,我得到以下错误:
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:429)
它似乎在试图调用我想要返回的数组
经过一段时间的挖掘,我找到了如下解决方案:
(def test1 #([%]))
(test1 5)
(def test1 #(-> [%]))
(test1 5)
我有一些问题:
#([%])
不起作用?我对表达式#([x])
做了什么(>x(+1))
。在这种情况下,我甚至没有要传递的函数*在此上下文中,下一个函数是什么?我不明白为什么它解决了我的问题问题1 语法
#([%])
转化为:“创建一个函数,调用该函数时将计算表达式([%])
,其中%
是传递给函数的第一个(也是唯一的)参数”。此表达式具有函数调用的语法,[%]
是要调用的函数。使用宏扩展
,您可以看到发生了什么:
(macroexpand '#([%]))
;; => (fn* [p1__6926#] ([p1__6926#]))
clojure中的持久性向量类是clojure.lang.PersistentVector
。它们实现了arity1的IFn
接口,因此您可以将向量视为将索引映射到元素的函数。但是它们没有实现arity 0,这正是您试图调用的。换句话说,您的代码不起作用:
(def test1 #([%]))
(test1 5) ;; ERROR
但是,如果将参数0传递给函数[%]
,则返回元素:
(def test1 #([%] 0))
(test1 5)
;; => 5
你看到发生了什么吗?然而,对于您正在尝试做的事情,有一个更好的方法:[abc]
语法只是调用(vector abc)
的糖分。所以要想得到有效的东西,你可以
(def test1 vector)
(test1 5)
;; => [5]
问题2
线程优先宏的语法为(->x f0 f1 f2…
,其中x
是初始值,f0
,f1
等是函数调用,它们的第一个参数被忽略,由正在通过管道传递的值替换。同样,我们可以使用macroexpand来理解:
(macroexpand '(-> x f0 f1 f2))
;; => (f2 (f1 (f0 x)))
但是在您的例子中,函数调用被忽略了。要分析第二个示例,我们需要使用clojure.walk/macroexpand all
进行完全扩展,因为我们有嵌套的宏:
(clojure.walk/macroexpand-all '#(-> [%]))
;; => (fn* [p1__6995#] [p1__6995#])
尽管如此,我们也可以一步一步地看:
(macroexpand '#(-> [%]))
;; => (fn* [p1__7000#] (-> [p1__7000#]))
(macroexpand '(-> [p1__7000#]))
;; => [p1__7000#]
所以要回答您的问题:
(>[%])
中没有下一个函数。下一个函数的数目可以是任何非负数,包括零,这是问题1的情况
语法#([%])
转化为:“创建一个函数,调用该函数时将计算表达式([%])
,其中%
是传递给函数的第一个(也是唯一的)参数”。此表达式具有函数调用的语法,[%]
是要调用的函数。使用宏扩展
,您可以看到发生了什么:
(macroexpand '#([%]))
;; => (fn* [p1__6926#] ([p1__6926#]))
clojure中的持久性向量类是clojure.lang.PersistentVector
。它们实现了arity1的IFn
接口,因此您可以将向量视为将索引映射到元素的函数。但是它们没有实现arity 0,这正是您试图调用的。换句话说,您的代码不起作用:
(def test1 #([%]))
(test1 5) ;; ERROR
但是,如果将参数0传递给函数[%]
,则返回元素:
(def test1 #([%] 0))
(test1 5)
;; => 5
你看到发生了什么吗?然而,对于您正在尝试做的事情,有一个更好的方法:[abc]
语法只是调用(vector abc)
的糖分。所以要想得到有效的东西,你可以
(def test1 vector)
(test1 5)
;; => [5]
问题2
线程优先宏的语法为(->x f0 f1 f2…
,其中x
是初始值,f0
,f1
等是函数调用,它们的第一个参数被忽略,由正在通过管道传递的值替换。同样,我们可以使用macroexpand来理解:
(macroexpand '(-> x f0 f1 f2))
;; => (f2 (f1 (f0 x)))
但是在您的例子中,函数调用被忽略了。要分析第二个示例,我们需要使用clojure.walk/macroexpand all
进行完全扩展,因为我们有嵌套的宏:
(clojure.walk/macroexpand-all '#(-> [%]))
;; => (fn* [p1__6995#] [p1__6995#])
尽管如此,我们也可以一步一步地看:
(macroexpand '#(-> [%]))
;; => (fn* [p1__7000#] (-> [p1__7000#]))
(macroexpand '(-> [p1__7000#]))
;; => [p1__7000#]
所以要回答您的问题:
(>[%])
中没有下一个函数。下一个函数的数目可以是任何非负数,包括零,这是(>[%])
@Rulle给出了详细的解释
我可以指出最重要的部分吗?从Clojure.org
上可以看到:
;; DO NOT DO THIS
#([%])
所以,不要那样做这是一个愚蠢的把戏,只会引起困惑和痛苦。你为什么要这样做?@Rulle对细节做了详尽的解释 我可以指出最重要的部分吗?从
Clojure.org
上可以看到:
;; DO NOT DO THIS
#([%])
所以,不要那样做这是一个愚蠢的把戏,只会引起困惑和痛苦。你为什么要这样做呢?规范应该是
#(向量x)
。答案谢谢@leetwinski,我使用这些函数只是为了学习。本教程本身建议使用vector
函数。您的主要问题将在中详细介绍。不过,我不想以重复的形式结束这篇文章,因为对->
的额外讨论很有用。规范是#(向量x)
。答案谢谢@leetwinski,我使用这些函数只是为了学习。本教程本身建议使用vector
函数。您的主要问题将在中详细介绍。不过,我不想以重复的形式结束这篇文章,因为关于->
的附加讨论很有用。谢谢您的支持