关闭 Clojure 中函数的哈希图

Closing over a hash-map of functions in Clojure

我有一组函数都具有相同的第一个参数。

(defn get-file [dir filename] ...)
(defn write-file [dir filename] ...)

基本上,我想一次部分应用所有这些。似乎我可以将它们全部包装在这样的函数中:

(defn get-fns [dir]
  {:get-file (fn [filename] ...)
   :write-file (fn [filename] ...)})

但是访问这些函数似乎有点烦人。

(let [fns (get-fns dir-name)]
  ((fns :get-file) filename)))

我想我也可以使用可变的 var,但这似乎不太实用。有 canonical/idiomatic 的方法吗?

让我们想一想:你有一个事物列表,你想对每个事物应用一些东西,所以 map。你想对他们应用什么?您想要部分应用第一个参数,因此 partial。然后你想对每个值都有一个唯一的引用,所以在列表上使用解构。

将所有这些加起来,假设 dirget-filewrite-file 都已定义,您会做

(let [[get-file-here write-file-here] (map #(partial % dir) [get-file write-file])]
  ...)

这是一个完整的例子

(let [[add-to-3 sub-from-3] (map #(partial % 3) [+ -])]
  (prn (add-to-3 2))                                    ; 5
  (prn (sub-from-3 5)))                                 ; -2

所以我们想要一系列可以在本地绑定上下文中使用的部分应用程序。

(defn get-fns
  [dir]
  {:get-f (partial get-file dir)
   :write-f (partial write-file dir)})

然后,在本地绑定中,我们可以使用它们

(let [{:keys [get-f write-f]} (get-fns dir)]
   (get-f file-name))

(您当然可以自由使用您的原始关键字,通过更改关键字,我明确指出 get-f 来自 get-fns 而不是全局绑定的 var)。