2013-02-08 14 views
9

Diciamo che ho un X.clojurescript e uno spazio dei nomi X.clojure. Tutto in X.clojurescript è codice Clojurescript, tutto in X.clojure è il codice Clojure. Purtroppo, non posso definire le macro direttamente ClojureScript, devo definirli in Clojure e poi portarli in uno spazio dei nomi ClojureScript utilizzandoCome faccio a gestire il codice Clojurescript richiesto dai macro Clojurescript?

(ns X.clojurescript.abc 
    (:require-macros [X.clojure.def :as clj])) 

Questo va bene. Tuttavia, cosa succede se la macro (definita in X.clojure) avrà bisogno di fare riferimento a qualcosa definito in uno spazio dei nomi Clojurescript (X.clojurescript)? Il problema è che il compilatore Clojure non cerca nel mio spazio dei nomi Clojurescript (una directory separata) quando risolve altri spazi dei nomi.

Ho risolto questo problema creando semplicemente uno spazio dei nomi nel mio codice Clojure che ha lo stesso spazio dei nomi e la definizione necessaria che esiste in Clojurescript, ma questo sembra un po 'stupido. Quindi, per esempio, se ho bisogno di X.clojurescript.abc.y nella mia macro, creerò solo uno spazio dei nomi aggiuntivo sul lato Clojure che defs un dummy y nella mia versione Clojure di X.clojurescript.abc; tipo di stupido.

Come faccio a gestire una macro che deve fare riferimento a qualcosa sul lato Clojurescript?

+0

Crea la tua macro in modo tale da prendere tutte le cose necessarie dal clojurescript come parametro. Se potessi aggiungere del codice, sarà molto più facile rispondere alla tua domanda specifica – Ankur

+2

Non credo di aver capito la tua domanda. La tua macro deve * generare * il codice che verrà quindi valutato in clojurescript. Quindi, se si deve fare riferimento a qualsiasi def di clojurescript, non sarebbe sufficiente generare il simbolo nell'espansione della macro? – KIMA

+0

'si riferisce a qualcosa sul lato Clojurescript 'ne hai bisogno al momento dell'espansione della macro o questo sarà qualcosa che verrà emesso nel codice di uscita? – Ankur

risposta

6

L'unica volta che una macro richiede uno spazio dei nomi specifico al momento della definizione è se la macro utilizza il codice di tale spazio dei nomi per generare l'elenco di simboli che restituirà.

si può seguire con questi esempi nel repl:

(defmacro foo 
    [a] 
    `(bar/bar ~a)) 

la definizione di foo compilerà anche se bar non è uno spazio dei nomi definito

(foo :a) 

chiamando foo sarà ora fallire perché si non ho ancora definito lo spazio dei nomi della barra, o la barra delle funzioni

(ns bar) 
(defn bar 
    [x] 
    [x x]) 

definisce bar nel namespace bar

(ns user) 
(foo :a) 

=> [: a: a]

Avviso quel bar non ha bisogno di esistere al momento della definizione di foo. In realtà il namespace non ha nemmeno bisogno di esistere al momento della definizione di foo.

+0

La compilazione è una cosa, ma per quanto riguarda la richiesta di una libreria sul lato ClojureScript? Nell'esempio sopra riportato, sembra che sia necessario richiedere lo spazio dei nomi delle barre nel modulo ClojureScript che chiama la macro foo, il che significa che il modulo chiamante deve conoscere i dettagli di implementazione della macro. –

+0

Un esempio del problema che ho citato è sperimentato dalla libreria Hiccups. Puoi vedere la loro soluzione qui, che è una specie di hacky: https://github.com/teropa/hiccups#usage –

+1

Penso che questo sia un problema fondamentale con l'implementazione del clojurescript così com'è.Sto suggerendo quello che credo sia il modo migliore per lavorarci, ma capisco che non è l'ideale. Ma fondamentalmente non è diverso dal modo in cui si useranno macro in puro codice clojure: la macro ricerca le funzioni che genera i simboli al momento dell'invocazione. – noisesmith

Problemi correlati