如何获取 ClojureScript 命名空间中 public 函数的列表?

How do I get a list of public functions in a ClojureScript namespace?

我想从另一个命名空间获取 public 函数的列表,以便它们可以作为命令公开。

Clojure 的 similar question 似乎很接近,但似乎不适用于 ClojureScript。

有 Clojurescript 的答案,但它们要么只显示如何将它们打印到 REPL,要么 return 所有成员而不是仅 public 公开的成员。

ClojureScript 没有 resolve function. It is possible to mimic the behavior using hacks, e.g., this one:

(defn ->js [var-name]
  (-> var-name
      (clojure.string/replace #"/" ".")
      (clojure.string/replace #"-" "_")))

(defn invoke [function-name & args]
  (let [f (js/eval (->js function-name))]
    (apply f args)))

您链接的第二个问题的答案涉及 clojure.repl/dir 打印

的函数

a sorted directory of public vars in a namespace.

如果你可以打印它们,你可以用with-out-str把它们变成一个字符串。

现在假设我们有一个名为 demo.core 的名称空间和一个名为 add 的 public 函数:

(ns demo.core)

(defn add [a b]
  (println "hello from add")
  (+ a b))

我们可以从 demo.core 中检索 public fns 作为字符串,如下所示:

(defn public-fns
  "Returns coll of names of public fns in demo.core"
  []
  (as-> (with-out-str (clojure.repl/dir demo.core)) public-fns
    (clojure.string/split public-fns #"\n")
    (map (fn [s] (str "demo.core/" s)) public-fns)))

所以使用 with-out-str 我们将它们变成一个字符串列表,然后在换行符上拆分,然后在 public 函数的名称前加上 "demo.core".

然后,使用我们之前创建的 invoke 函数,我们可以获得 add 并使用参数 1 和 2 调用它:

(invoke (first (public-fns)) 1 2)
;; "hello from add"
;; => 3

这一切都非常 hacky,在高级编译中可能会出错,但它确实有效。