Reputation: 841
I want to get a list of public functions from another namespace so they can be exposed as commands.
A similar question for Clojure seemed close, but does not seem to work on ClojureScript.
Another question has answers for Clojurescript, but they either only show how to print them to the REPL, or return all members instead of only the publicly exposed ones.
Upvotes: 3
Views: 434
Reputation: 10474
ClojureScript does not have a 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)))
The second question you linked has an answer that refers to the clojure.repl/dir
function which prints
a sorted directory of public vars in a namespace.
If you can print them, you can turn them into a string with with-out-str
.
Now let's assume we have a namespace called demo.core
with one public function called add
:
(ns demo.core)
(defn add [a b]
(println "hello from add")
(+ a b))
We can retrieve the public fns from demo.core
as strings as follows:
(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)))
So with with-out-str
we turn them into a list of strings, then split on newline, then prepend the names of public functions with "demo.core".
Then, using our earlier created invoke
function, we can obtain add
and invoke it with the arguments 1 and 2:
(invoke (first (public-fns)) 1 2)
;; "hello from add"
;; => 3
This is all very hacky, and it might break in advanced compilation, but it works.
Upvotes: 3