2014-04-28 11 views

risposta

1

Questo non è possibile, come una volta si utilizza la modalità di compilazione avanzata di ClojureScript poi tutti i nomi delle funzioni sono "munged", quindi non ci sarebbe modo di mappare una stringa a una funzione mungita quando si desidera chiamarla

3

Avevo bisogno di un modo di chiamare una funzione il cui ns/nome è caricato dinamicamente. Come notato, non esiste un modo supportato per farlo. Tuttavia, questo è ciò che gli hack sono per. Ecco quello che ho finito per fare:

cljs Calling:

(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 dinamicamente risolti:

(ns my-ns) 
(defn ^:export my-fun [args] ...) 

I metadati esportazione dice al compilatore di chiusura non munge il nome, quindi funziona anche con la compilazione in modalità avanzata. Inutile dire che questo non è un codice solido come il rock che è garantito per funzionare in futuro, ma tu hai l'idea.

3

Una soluzione abbastanza hacker che dovrebbe funzionare:

(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 
0

Finché non si utilizza l'ottimizzazione avanzata per il compilatore:

(def global (this-as this this)) 

(defn call [fname & args] 
    (.apply (aget global fname) global args)) 

(call "String" 123) 

global è legato al global object per qualsiasi piattaforma da utilizzando l'operatore this nell'ambito globale. È possibile utilizzare .call invece di .apply come in:

(.call (aget global "String") global 123) 

La stessa tecnica può essere utilizzata anche con altri oggetti rispetto al globale.