2016-08-09 23 views
0

Gibt es in Chicken Scheme eine Möglichkeit, zur Laufzeit zu bestimmen, ob eine Variable aktuell definiert ist?Wie kann man feststellen, ob eine Variable in Chicken Scheme existiert?

(let ((var 1)) 
(print (is-defined? var)) ; #t 

(print (is-defined? var)) ; #f 

EDIT: XY Problem.

Ich schreibe ein Makro, das Code generiert. Dieser generierte Code muss das Makro in gegenseitiger Rekursion aufrufen - das Makro, das einfach aufgerufen wird, funktioniert nicht. Wenn das Makro rekursiv aufgerufen wird, muss es sich anders verhalten als beim ersten Aufruf. Ich würde eine verschachtelte Funktion verwenden, aber uh .... es ist ein Makro.

Raute Beispiel:

(defmacro m (nested) 
(if nested 
    BACKQUOTE(print "is nested") 
    BACKQUOTE(m #t) 

(ja, ich weiß Schema nicht defmacro nicht verwendet, aber ich komme von Common Lisp Auch kann ich nicht einfache Anführungszeichen scheinen, ohne es hier zu setzen alle gehen. zur Hölle.)

Ich möchte nicht, dass der Aufruf INITIAL des Makros ein zusätzliches Argument nimmt, das nur dann Bedeutung hat, wenn es rekursiv aufgerufen wird. Ich will es auf andere Weise wissen.

Kann ich den generierten Code abrufen, um ein Makro aufzurufen, das innerhalb des ersten Makros verschachtelt ist und möglicherweise nicht an der Aufrufsite vorhanden ist? Beispielsweise Code generieren, der (,other-macro) statt (macro) aufruft?

Aber das sollte nicht funktionieren, weil ein Makro-Objekt nicht ein First-Class ist wie eine Funktion ...

+0

Dies sollten Sie zur Kompilierzeit/Schreibzeit wissen. XY? Was planen wir damit? – Sylwester

+0

Ich habe Details zu meiner Frage hinzugefügt. –

Antwort

0

Es gibt keine Möglichkeit, dass im Allgemeinen zu tun, denn Scheme lexikalischen wird. Es macht nicht viel Sinn zu fragen, ob eine Variable definiert ist, wenn ein Verweis auf eine undefinierte Variable ein Fehler ist.

Für Toplevel/globale Variablen können Sie die symbol-utils egg verwenden, aber es wird wahrscheinlich nicht wie erwartet funktionieren, wenn man bedenkt, dass globale Variablen in Modulen auch als etwas anderes geschrieben werden.

Vielleicht, wenn Sie sagen können, was Sie wirklich versuchen zu tun sind, kann ich Ihnen mit einer alternativen Lösung helfen.

+0

Ich versuche, ein 'Destructuring-bind'-Makro zu schreiben, das Schlüsselwort und optionale Parameter unterstützt. Dazu muss ich rekursiv Code generieren. Die rekursiven Aufrufe müssen wissen, ob sie sich im Schlüsselwort-Modus befinden.Ich kann eine verschachtelte Methode nicht verwenden, da es ein Makro ist und rekursiv Code generieren muss, der das Makro erneut aufruft. Es macht keinen Sinn, dass der Makro einen Modus-Parameter akzeptiert, denn dann müsste ich ihn in der ersten Instanz mit einem Null-Argument aufrufen. Was ich brauche, ist eine lexikalische Bindung, die existieren kann oder nicht, und dementsprechend reagieren. –

1

Wenn Sie rekursive Makros schreiben, habe ich den Eindruck, dass Sie eine Makroerweiterung (m a b ...) haben, die sich in eine (m-helper a (b ...)) verwandelt, die sich in (let (a ...) (m b ...)) verwandeln könnte. Das ist nicht direkt rekursiv, da Sie Code in Code verwandeln, der zufällig ein Makro enthält.

Mit destructuring-bind müssen Sie wirklich nur zwei Variablen im Auge behalten. Ein für car und ein für cdr und mit einem impliziten Umbenennung Makro werden der Stoff nicht aus der Form kommenden umbenannt und somit hygienischer: Sie verwenden die mitgelieferte compare? Prozedur

(define-syntax destructuring-bind 
    (ir-macro-transformer 
    (lambda (form inject compare?) 
    (define (parse-structure structure expression optional? body) 
     ;;actual magic happens here. Returns list structure with a mix of parts from structure as well as introduced variables and globals 
     ) 

    (match form 
     [(structure expression) . body ] 
     `(let ((tmp ,expression)) 
      ,(parse-structure structure 'tmp #f body)))))) 

Um zu überprüfen, ob etwas von der Eingabe das gleiche Symbol ist. z.B. (compare? expression '&optional).

+0

Das stimmt, das Makro kann ein optionales Argument verwenden. Alternativ können Sie mit 'let-syntax' ein Makro erstellen, das lokal sichtbar ist. Und Sie können Hilfsprozeduren aus Low-Level-Makros aufrufen: Es gibt keinen Grund, warum ein Makro nur andere Makros aufrufen sollte. Denken Sie daran, ihre Bibliothek mit 'Syntax verwenden' zu laden oder sie selbst in einem 'Beginne-für-Syntax'-Formular zu definieren. Sehen Sie sich zur Inspiration die Implementierung des [matchable] (http://wiki.call-cc.org/eggref/4/matchable) Eies an, das dem sehr nahe kommt. Und da ist das [Bindings] (http://wiki.call-cc.org/eggref/4/bindings) Ei. – sjamaan