I'm searching for a way to call a function given its string name in clojureScript.
Something like:
(call "my-fun" args)
Any help welcome
A pretty hackish solution that should work:
(ns eval.core
(:require [clojure.string :as str]))
(defn ->js [var-name]
(-> var-name
(str/replace #"/" ".")
(str/replace #"-" "_")))
(defn invoke [function-name & args]
(let [fun (js/eval (->js function-name))]
(apply fun args)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Usage:
(ns example.core
(:require [eval.core :as e]))
(defn ^:export my-fn [arg1 arg2] ;; Note the export!
(println arg1 arg2)
arg2)
(e/invoke "example.core/my-fn" 5 6) ;=> 5 6
I needed a way of calling a function whose ns/name is loaded dynamically. As noted, there is no supported way of doing so. However, that's what hacks are for. Here's what I ended up doing:
Calling cljs:
(js/proxy "my-ns/my-fun" args)
Proxy.js:
function proxy() {
var args = Array.prototype.slice.call(arguments);
var nsFunc = args[0].replace(/-/g, "_").replace(/\//g, ".");
eval(nsFunc).apply(null, args.slice(1));
}
Dynamically resolved cljs:
(ns my-ns)
(defn ^:export my-fun [args] ...)
The export metadata tells the closure compiler not to munge the name, so this works even with advanced mode compilation. Needless to say, this isn't rock-solid code that's guaranteed to work in the future - but you get the idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With