2010-07-16 1 views
7

Ich möchte testen können, ob eine Variable definiert ist, bevor Sie darauf zugreifen.Wie teste ich, ob eine Variable definiert ist, bevor Sie sie referenzieren?

Ich mag eine globale, die eine "Debug-Ebene" angibt. Wenn der Debug-Level 0 ist, wird keine zusätzliche Ausgabe ausgegeben. Wenn größer als 1, wird Debug-Ausgabe gegeben, mit mehr Ausführlichkeit bei größeren Zahlen.

Ich würde auch gerne einrichten, so dass die Verfahren laufen würden, und eine Stufe 0 annehmen, wenn ich nicht dazu gekommen wäre, sie zu definieren. Etwas wie:?.. (Wo defined? die Magie ist, weiß ich nicht, wie zu tun

(if (and (defined? debug-level) (> debug-level 1)) 
    (diplay "Some debugging info")) 

Ich habe in The Scheme Programming Language, 4th Edition durch die Zusammenfassung von Formen sah die einzige, die ich sah, als eine Möglichkeit, identifier? war es tat . nicht funktionieren

ich 1.16.6 SISC bin mit (Ansprüche R5RS Compliance) und v8 Petite Scheme Chez (behauptet R6RS Compliance)

EDIT ich eval mit einem guard wie versucht Verpackung:

Da 'debug-level angegeben ist, kann es ausgewertet und an eval übergeben werden. Dann, wenn eval versucht, es auszuwerten, würde ein Fehler passieren, den ich gehofft hatte guard würde fangen. Es tat es nicht.

EDIT 2 Ich erkannte, dass ich die Debug-Tracing in einem separaten Verfahren und dass die Datei, die definiert, dass dieses Verfahren können auch definieren debug-level mit einem Standardwert von 0. Die Gründe für die Verwendung eines separaten Verfahrens senken wickeln wollte die Anzahl der Zeilen in den Prozeduren, die funktionieren, und auch die Umleitung der Debug-Ausgabe bei Bedarf zu ermöglichen.

Antwort

4

Dies ist völlig auf die Implementierung zu bieten, und es sieht aus wie die meisten Implementierungen nicht zufriedenstellend zur Verfügung stellen.

In SISC Schema sieht es aus wie Sie GETPROP in diesem Sinne aber Umgebungen nicht automatisch aktualisiert oh verwenden können, suchen, gibt es dieses Ding INTERACTION-ENVIRONMENT genannt, dass Sie verwenden können:

 
#;> (getprop 'cons (interaction-environment)) 
#<native procedure cons> 
#;> (getprop 'x (interaction-environment)) 
#f 
#;> (define x 100) 
#;> (getprop 'x (interaction-environment)) 
100 

Aber es funktioniert nur auf der obersten Ebene.

 
#;> (define (foo y) 
    (let ((e (interaction-environment))) 
    (display "Is X bound? ") (display (getprop 'x e)) 
    (newline) 
    (display "Is Y bound? ") (display (getprop 'y e)) 
    (newline))) 
#;> (foo 1) 
#;> Is X bound? 100 
Is Y bound? #f 

Für Chez haben Sie TOP-LEVEL-BOUND? und INTERACTION-ENVIRONMENT wieder.

+0

Danke. Ich hatte Angst, dass die Antwort nicht weit tragbar wäre, dass es entweder etwas Neues in R6RS oder eine Implementierung wäre. +1, aber ich werde diese Antwort etwas altern lassen, um zu sehen, ob irgendwelche besseren Ideen gepostet werden, bevor sie als korrekt akzeptiert werden. –

1

Um ein wenig zu sichern, das Problem mit einer defined? Funktion besteht darin, dass, wenn Sie

(defined? debug-level) 

Scheme schreiben versucht, debug-level zu bewerten, was natürlich ein Fehler ist, da er nicht definiert ist. Eine solche Form müsste als Sonderfall intern vom Compiler/Interpreter implementiert werden.

Eine solche spezielle Form ist nicht Teil des R5RS-Standards (es sei denn, ich habe es verpasst, bitte double-check). In Bezug auf R5RS-Schemata haben Sie also kein Glück, es sei denn, Sie finden ein Schema, das dies als eine nicht standardmäßige Erweiterung implementiert.

+0

Ich fragte nicht nach einer Funktion 'definiert?' weil, wie Sie sagen, eine Funktion nicht funktionieren würde. Aber eine Funktion würde auch nicht für "wenn" funktionieren, und doch hat das Schema "wenn". In anderen Arbeitsbereichen, auf der Suche nach einer speziellen Form oder einer anderen Möglichkeit, die Ergebnisse zu erzielen. (Makro vielleicht?) –

+1

Sicher. Was ich sagen wollte, ist, dass dies eine der eingebauten Formen sein müsste, die die Sprache bietet, wie zum Beispiel "if", und die Spezifikation (zumindest R5RS) scheint keine zu enthalten. –

2

Clunky, aber praktikable Lösung für R5RS. Verwenden Sie die oft vernachlässigte/vergessene Fähigkeit der Let-Syntax, um Schlüsselwörter neu zu definieren. Das ist klobig, weil Ihre gesamte Datei in eine Let-Syntax eingebettet ist und weil sie jeder Definition etwas Overhead hinzufügt. Ich verwende eine assoziative Liste, um Definitionen zu behalten, eine Hash-Tabelle wäre eine bessere Wahl.

(define define-list '()) 
(define define-list-add 
    (lambda (key value) 
    (set! define-list (cons `(,key ,value) define-list)))) 

(let-syntax (
      (define (syntax-rules() 
         ((_ (pro-name args ...) body ...) 
         (begin 
          (define (pro-name args ...) body ...) 
          (define-list-add pro-name '((pro-name args ...) body ...)))) 
         ((_ pro-name pro) (begin 
              (define pro-name pro) 
              (define-list-add 'pro-name 'pro))) 

         )) 
      (defined? 
       (syntax-rules() 
       ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f))))) 
      ) 
    (define y (lambda() x)) 

    (display (defined? y)) 
    (newline) 
    (display (defined? x)) 
) 

druckt

#t 
#f 

Unten in Schlägern: genannt define-Liste ist ein Modul neu zu definieren, definieren zu speichern jedes Symbol und Definition in einer Liste verwendet. Das Makro definiert? Sieht in dieser Liste nach, ob das Wetter oder nicht das Symbol definiert wurde.

(module qdefine mzscheme 
    (provide ;(all-from-except mzscheme let) 
    (rename define olddefine) 
    (rename quote-define define) 
    defined?) 

    (define define-list '()) 
    (define define-list-add 
    (lambda (key value) 
     (set! define-list (cons `(,key ,value) define-list)))) 

    (define-syntax quote-define 
    (syntax-rules() 
     ((_ (pro-name args ...) body ...) 
     (begin 
     (define (pro-name args ...) body ...) 
     (define-list-add pro-name '((pro-name args ...) body ...)))) 
     ((_ pro-name pro) (begin 
          (define pro-name pro) 
          (define-list-add 'pro-name 'pro))) 

    )) 

    (define-syntax defined? 
    (syntax-rules() 
     ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f))))) 
) 
(require 'qdefine) 

(define y (lambda() x)) 

(defined? y) 
(defined? x) 

In guile ist es nur definiert? anscheinend: http://www.delorie.com/gnu/docs/guile/guile_289.html

+1

Racket hat die Reflexionswerkzeuge, um so etwas zu tun, aber solche Dinge (einschließlich Interaktionsumgebung, was auch immer Guile tut, usw.) sind immer wackelige Art von Lösungen, die auf die eine oder andere Weise leiden. –

+0

+1 für die tragbare Lösung. –