clojure Makro um Funktionen zu generieren

7

Ich versuche ein Makro zu schreiben, das n Funktionen erzeugt. Folgendes habe ich bisher:

%Vor%

Der Fehler, den ich bekomme, ist:

%Vor%

Und ich bin nicht wirklich sicher, was das bedeutet, aber ich habe diese vage Vorstellung, dass (für ...) nicht so funktioniert, wie ich denke, dass es in einem Makro ist.

    
Kevin 21.10.2011, 16:22
quelle

2 Antworten

17

Sie sind verwirrt über die Unterscheidung zwischen Laufzeit und Kompilierzeit sowie zwischen Makros und Funktionen. Das Lösen eines Makroproblems mit eval ist niemals die richtige Antwort: Stellen Sie stattdessen sicher, dass Sie Code zurückgeben, der das tut, was Sie tun möchten. Hier ist eine minimale Änderung, damit Ihre ursprüngliche Version funktioniert.

Die wichtigsten Änderungen sind:

  1. defn-from ist eine Funktion, kein Makro - Sie möchten nur eine einfache Möglichkeit zum Erstellen von Listen, die das Hauptmakro für das Einfügen in das Ergebnisformular verantwortlich ist. Sie möchten nicht ein Makro hier haben, weil es nicht in den Körper von make-placeholders expandiert werden soll.

  2. make-placeholders beginnt mit einem do , und seine for außerhalb eines Syntax-Zitats. Dies ist der wichtigste Teil: Sie möchten, dass der an den Benutzer zurückgegebene Code wie (do (defn ...)) aussieht, als ob sie alles manuell eingegeben hätten - nicht (for ...) , was immer möglich war Definieren Sie eine einzelne Funktion.

%Vor%

1 Sehr, sehr selten

Bearbeiten

Sie können dies auch komplett ohne Makros tun, indem Sie eine Funktion zum Erstellen von Funktionen verwenden und die untergeordnete Operation intern anstelle von def verwenden. Es erweist sich tatsächlich als viel einfacher:

%Vor%     
amalloy 21.10.2011, 19:54
quelle
3

Macroexpanding sobald die (make-placeholders 9) Ausdruck ich bekomme dies:

%Vor%

Also defn-from erwartet eine Zeichenkette als erstes Argument, aber weil es ein Makro ist, wird (str "_" i__1862__auto__) nicht ausgewertet und ist daher als Liste hinterher.

Ich habe eine Weile mit dem herumgespielt und kam dabei auf:

%Vor%

Macroexpanding (make-placeholders 3) gibt

%Vor%

was ich beabsichtigt habe und dies evaluiere definiert die Funktionen _0 , _1 und _2 :

%Vor%

Ok, das funktioniert, aber ich bin mir immer noch nicht sicher, ob das eine gute Idee ist.

Zuerst eval ist böse . Ok, es könnte auch ohne eval gemacht werden, aber stattdessen mit do (ersetze map eval in meiner Lösung mit do ). Möglicherweise machen Sie Ihren Code jedoch schwer verständlich, weil Sie Funktionen erstellen, die nirgendwo in Ihrem Code definiert sind. Ich erinnere mich, dass ich, als ich gerade Clojure benutzt habe, eine Bibliothek nach einer Funktion durchsucht habe und sie nicht finden konnte. Ich fing an, yikes zu denken, dieser Typ muss irgendwo ein Makro definiert haben, das die Funktion definiert, nach der ich suche, wie werde ich jemals verstehen, was vor sich geht? Wenn die Leute Clojure benutzen, dann wird es eine höllische Sauerei sein und alles, was die Leute über Perl gesagt haben, in den Schatten stellen ... Es stellte sich heraus, dass ich nur die falsche Version anschaute - aber Sie könnten es sein sich selbst und andere für etwas Elend aufstellen.

Nachdem dies gesagt wurde, könnte es geeignete Anwendungen dafür geben. Oder Sie könnten etwas Ähnliches verwenden, um Code zu generieren und in eine Datei zu schreiben (dann wäre der Quellcode für die Überprüfung verfügbar). Vielleicht kann jemand erfahrener hereinspielen?

    
Paul 21.10.2011 16:38
quelle

Tags und Links