我正在寻找一种方法来调用一个函数,在clojureScript中给出它的字符串名称。
类似的东西:
(call "my-fun" args)
欢迎任何帮助
答案 0 :(得分:5)
一个非常糟糕的解决方案应该可行:
(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
答案 1 :(得分:3)
我需要一种调用动态加载ns / name的函数的方法。如上所述,没有受到支持的方式。然而,这就是黑客的目的。这就是我最终做的事情:
调用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));
}
动态解析的cljs:
(ns my-ns)
(defn ^:export my-fun [args] ...)
导出元数据告诉闭包编译器不要使用名称,因此即使使用高级模式编译也是如此。毋庸置疑,这不是一个坚如磐石的代码,可以保证在将来有效 - 但是你明白了。
答案 2 :(得分:1)
这是不可能的,因为一旦你使用clojurescript的高级模式编译,那么所有的函数名都是“munged”,所以当你想要调用它时,没有办法将字符串映射到munged函数
答案 3 :(得分:0)
只要您不对编译器使用高级优化:
(def global (this-as this this))
(defn call [fname & args]
(.apply (aget global fname) global args))
(call "String" 123)
通过在全局范围内使用global
运算符, this
绑定到任何平台的global object。您可以使用.call
代替.apply
,如下所示:
(.call (aget global "String") global 123)
同样的技术也可以用于除全局之外的其他对象。