2013-02-08 4 views
9

Sagen wir, ich habe ein X.clojurescript und einen X.clojure Namespace. Alles in X.clojurescript ist Clojurescript-Code, alles in X.clojure ist Clojure-Code. Leider kann ich keine Makros direkt in Clojurescript definieren, habe ich sie in Clojure definieren und sie dann in ein NamespaceWie gehe ich mit dem erforderlichen Clojurescript-Code von Clojurescript-Makros um?

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

Das ist in Ordnung mit Clojurescript zu bringen. Was aber, wenn das Makro (in X.clojure definiert) auf etwas verweisen muss, das in einem Clojurescript-Namespace (X.clojurescript) definiert ist? Das Problem ist, dass der Clojure-Compiler nicht in meinen Clojurescript-Namespace (ein separates Verzeichnis) schaut, wenn andere Namespaces aufgelöst werden.

Ich habe dieses Problem gelöst, indem ich einfach einen Namespace in meinem Clojure-Code erstelle, der denselben Namespace und die gleiche Definition wie in Clojurescript hat, aber das scheint irgendwie dumm zu sein. Wenn ich zum Beispiel X.clojurescript.abc.y in meinem Makro benötige, erstelle ich einfach einen zusätzlichen Namespace auf der Clojure-Seite, der in meiner Clojure-Version von X.clojurescript.abc ein Dummy-Y enthält; irgendwie dumm.

Wie gehe ich mit einem Makro um, das auf etwas auf der Clojurescript-Seite verweisen muss?

+0

Machen Sie Ihr Makro so, dass es alle erforderlichen Dinge aus Clojurescript als Parameter übernimmt. Wenn Sie etwas Code hinzufügen können, wird es viel einfacher sein, Ihre spezifische Abfrage zu beantworten – Ankur

+2

Ich glaube nicht, dass ich Ihre Frage verstehe. Ihr Makro muss * den Code erzeugen, der dann in Clojurescript ausgewertet wird. Wenn Sie also auf ein beliebiges Clojurescript-Def verweisen müssen, reicht es nicht aus, das Symbol in der Erweiterung des Makros zu erzeugen? – KIMA

+0

'beziehen Sie sich auf etwas auf der Clojurescript-Seite' Sie brauchen das bei der Makroerweiterung oder wird dies etwas sein, das im Ausgabecode ausgegeben wird? – Ankur

Antwort

6

Die einzige Zeit, zu der ein Makro zum Zeitpunkt der Definition einen bestimmten Namespace benötigt, ist, wenn das Makro Code aus dem Namespace verwendet, um die Liste der Symbole zu generieren, die zurückgegeben werden.

Sie können mit diesen Beispielen im ers folgen zusammen:

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

die Definition von foo kompilieren obwohl bar ist kein definierter Namespace

(foo :a) 

foo Aufruf wird nun, weil Sie scheitern den Bar-Namespace oder die Funktionsleiste noch nicht definiert

definiert Bar in der Bar-Namespace

(ns user) 
(foo :a) 

=> [: a: a]

Beachten Sie, dass Bar nicht zum Zeitpunkt der foo Definition existieren muss. Tatsächlich muss der Namespace nicht einmal zur Zeit der Definition von foo existieren.

+0

Kompilierung ist eine Sache, aber was ist mit einer Bibliothek auf der ClojureScript-Seite? In Ihrem obigen Beispiel scheint es erforderlich zu sein, dass Sie den Bar-Namespace im ClojureScript-Modul benötigen, das den foo-Makro aufruft, was bedeutet, dass das aufrufende Modul Implementierungsdetails über das Makro kennen muss. –

+0

Ein Beispiel für das Problem, das ich erwähnte, wird von der Hiccups-Bibliothek erfahren. Sie können ihre Lösung hier sehen, die Art von Hacky ist: https://github.com/teropa/hiccups#usage –

+1

Ich denke, das ist ein grundlegendes Problem mit Clojurescript-Implementierung, wie es existiert.Ich schlage vor, was ich glaube, um der beste Weg zu sein, damit zu arbeiten, aber ich verstehe, dass es weniger als ideal ist. Aber grundsätzlich unterscheidet sich das nicht davon, wie man Makros im reinen Clojure-Code verwenden würde - das Makro sucht nach den Funktionen, für die es Symbole zur Aufrufzeit erzeugt. – noisesmith

Verwandte Themen