通过字符串名称调用clojurescript函数

时间:2014-04-28 15:53:53

标签: clojurescript

我正在寻找一种方法来调用一个函数,在clojureScript中给出它的字符串名称。

类似的东西:

(call "my-fun" args) 

欢迎任何帮助

4 个答案:

答案 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)

同样的技术也可以用于除全局之外的其他对象。