- >宏观和部分功能

时间:2015-03-21 22:37:27

标签: clojure

为什么我不能在->的链式通话中使用部分功能或匿名功能?

(->
    "123"
    seq
    sort
    reverse
    (partial apply str))
=> #<core$partial$fn__4230 clojure.core$partial$fn__4230@335f63af>

我原本以为会创建部分函数并立即应用于上一个函数的结果,但它实际上是自己返回的。

使用一个参数进行简单的函数链接当然可以正常工作:

(->
    "123"
    seq
    sort
    reverse
    clojure.string/join)

2 个答案:

答案 0 :(得分:2)

->宏定义为:

(doc ->)
-------------------------
clojure.core/->
([x & forms])
Macro
  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.

因此(apply str)会产生错误,因为前一个函数的列表是作为第二个参数输入的:

(->
    "123"
    seq
    sort
    reverse
    (apply str))
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn  clojure.core/apply (core.clj:624)

相反,应该使用宏 - &gt;&gt;,它适用于最后一项:

clojure.core/->>
([x & forms])
Macro
  Threads the expr through the forms. Inserts x as the
  last 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
  last item in second form, etc.

然后apply的解决方案如下所示:

(->>
  "123"
  seq
  sort
  reverse
  (apply str))
=> "321"

更新:->->>的扩展版本:

(macroexpand-1 '(->>
                 "123"
                 seq
                 sort
                 reverse
                 (apply str)))
=> (apply str (reverse (sort (seq "123"))))

从扩展版本中可以看出,表单(apply str)的解释方式只有区别。使用->插入第二项,而->>插入最后一项。

(macroexpand-1 '(->
                 "123"
                 seq
                 sort
                 reverse
                 (apply str)))
=> (apply (reverse (sort (seq "123"))) str)

答案 1 :(得分:2)

由于->->>只是宏,您可以使用->测试macroexpand-1展开的内容(请注意引用&#39;)

user=> (macroexpand-1 '(->
       "123"
       seq
       sort
       reverse
       (partial apply str)))

(partial (reverse (sort (seq "123"))) apply str)

这就是为什么你得到一个函数而不是一个字符串 - 结果是从reverseapply str作为参数返回的部分集合(这是一个函数)

如果由于某种原因你需要在->中应用一个函数,你应该把它包在parens中:

user=> (macroexpand-1 '(->
    "123"
    ((partial sort))  ; we add parens around so -> have plase to insert
   ))
((partial sort) "123")

或者您可以使用->>宏,因为它与partial执行相同的工作:

((partial str "hello ") "world")

"hello world"

(->> (str "hello ") "world")    ; expands to (str "hello " "world")

"hello world"