2010-04-05 20 views
5

如果我做到以下几点:(部分申请STR),并应用-STR在Clojure的 - >

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 [email protected]> 

...我收到了部分功能了。但是,如果我将它绑定到一个变量:

user=> (def apply-str (partial apply str)) 
#'user/apply-str 
user=> (-> ["1" "2" "3"] apply-str)  
"123" 

...代码按照我的意图工作。我会假设他们是同一件事,但显然情况并非如此。有人可以解释为什么这对我来说?

回答

6

- >是一个宏,所以它不必遵循您期望的应用程序规则。宏在表单评估之前转换源。尝试macroexpanding形式:

user> (macroexpand '(-> ["1" "2"] (partial apply str))) 
(partial ["1" "2"] apply str) 

什么是你想在这里通过实现“ - >”宏?

编辑:需要注意的是:

user> ((partial apply str) ["1" "2"]) 
"12" 
+0

我想写的代码比这更复杂一些。这只是一个简单的例子。我只想更好地理解' - >'宏如何工作。 :-) – 2010-04-05 11:39:38

+0

啊,陷阱。无论如何,你看到这里发生了什么? – 2010-04-05 14:02:59

+0

是的,我愿意。感谢您的回答! – 2010-04-09 11:35:53

5

你不必这样做的。

(->> ["1" "2" "3"] (apply str)) 

为什么不这样做呢?

4

第一个表达式,,扩展为:

(partial ["1" "2"] apply str)这基本上意味着:

创建从["1" "2"]的函数(这也是一个功能,因为载体是索引键的功能!)与瓦尔已经提供了applystr作为前两个参数。这个函数被打印成奇怪的#<core$partial...>字符串。 只有当这个函数被调用时,你会得到一个IllegalArgumentException,因为向量只有一个整数参数,而不是两个Var参数。

+0

请注意,Clojure是动态的向量是函数的事实并不重要,这个bug。 (部分“hello”“world”)也会返回一个函数 - 一个总是抛出的函数。 – cgrand 2010-04-12 09:31:52

0

->宏在第二个版本中增加了围绕apply-str的变形,这就是为什么宏扩展到最终调用函数的代码。看看为->的源代码,你可以看到:

(defmacro -> 
    "Threads the expr through the forms. Inserts x as the 
    second item in the first form, making a list of it if it is not a 
    list already. If there are more forms, inserts the first form as the 
    second item in second form, etc." 
    ([x] x) 
    ([x form] (if (seq? form) 
       (with-meta `(~(first form) ~x [email protected](next form)) (meta form)) 
       (list form x))) 
    ([x form & more] `(-> (-> ~x ~form) [email protected]))) 

相关的部分是,当它在处理两个参数,xform。如果form是seq,则将x作为该列表中的第二个参数插入。否则,宏将它自己放入一个列表中,并将它放入列表formx。这样您就可以使用裸符号作为包含一个符号的列表的简写。

user> (macroexpand '(-> 123 (foo))) 
(foo 123) 
user> (macroexpand '(-> 123 foo)) 
(foo 123) 
1

宏观- 通过形式第二个参数>线程的EXPR。在你的情况最终扩展到:(partial ["1" "2"] apply str),创建一个基于矢量的组合功能。

但要调用基于应用和STR上螺纹EXPR一个parital功能,因此需要:

(-> ["1" "2"] ((partial apply str))) 

好:这个代码我相当混乱,而不是惯用的Clojure。