我定义了一个函数映射:
(ns fs
(:require [folder/a :as a]
[folder/b :as b]
[folder/c :as c])
(def functions {:a a/f :b b/f :c c/f})
(doseq [[_ f] functions] (f))
现在我想在文件夹中添加更多的命名空间,我不想修改上面的代码。如何使用文件夹中的每个命名空间functions
动态填充f
。
首先是一些帮手:
(defn directory
"Get directory from path"
[path]
(clojure.java.io/file path))
(defn file-names
"Get file names of the files in the directory."
[files]
(map (fn [file] (.getName file)) files))
(defn namespace
"Remove the extension from the file name and prefix with folder-name"
[folder-name file-name]
(->> (clojure.string/split file-name #"\.")
(butlast)
(apply str)
(str folder-name ".")
(symbol)))
然后从您的文件夹中检索所有命名空间,您需要路径和文件夹名称:
(def namespaces
(let [names (->> "/path/to/your/folder-name"
directory
file-seq ;; Gets the tree structure of the directory
rest ;; Get rid of the the directory name
file-names)]
(map (partial namespace "folder-name") names)))
接下来通过以下方式获取每个命名空间中的公共函数ns-publics
:
(def functions
(->> namespaces
(map (juxt keyword (comp vals ns-publics)))
(into {})))
;; => prints {:namespace-key '(fn-a fn-b) :namespace-key2 '(fn-b fn-c)}
请注意,这会在命名空间键之后获取命名空间中所有公共函数的列表。
我们可以执行如下函数:
(doseq [[_ ns-fns] functions
f ns-fns] (f))
当然,这只适用于元数为零的函数。否则,您必须将参数传递给f
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句