用 Clojure 包装

Posted

技术标签:

【中文标题】用 Clojure 包装【英文标题】:Wrapping in Clojure 【发布时间】:2016-01-18 05:29:31 【问题描述】:

有时我很难在 Clojure 中包装函数或宏。

例如,Clojure Mongo 提供了一个 DSL 来查询集合:with-collection,这是一个宏。

一种使用方式如下所示:

(with-collection db coll
    (find )
    (sort (array-map :score -1 :name 1)))

我想创建一个接收排序函数并调用 with-collection 的函数。

(defn find [sort]
    (with-collection my-db my-coll
       (find )
       sort
)

如果我尝试调用该函数,我会收到以下错误:ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

(find (sort (array-map :score -1 :name 1))

我猜这是因为正在评估 sort 并且 with-collection 需要一个函数。

如果我尝试引用,则会收到以下错误:ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

(find (quote sort (array-map :score -1 :name 1)))

如果我尝试传递匿名函数,我会收到以下错误:ArityException Wrong number of args (1) passed to: main/eval139628/fn--139629

(find #(sort (array-map :score -1 :name 1))

是否可以使用函数来包装这种宏?谢谢。

【问题讨论】:

您的匿名函数不接受任何参数。试试#(sort % (array-map :score -1 :name 1)) 【参考方案1】:

问题是with-collection 宏扩展为->,因此您的函数应该将 coll 作为第一个参数。你也可以用你的`find 函数来影响monger find 函数。也许你应该这样做:

(defn my-find [sort]
  (with-collection my-db my-coll
    (find )
    sort)

然后这样称呼它:

(my-find #(sort % (array-map :score -1 :name 1))

【讨论】:

以上是关于用 Clojure 包装的主要内容,如果未能解决你的问题,请参考以下文章

Clojure 中的命名空间之间共享函数

用leiningen来运行和打包clojure项目

试玩儿Clojure

Clojure 学习笔记 1

clojure的语法糖

特价┃Clojure编程(china-pub首发)