2010-07-16 5 views
7

Mi piacerebbe essere in grado di verificare se una variabile è definita, prima di accedervi.Come verificare se una variabile è definita prima di farla riferimento?

Mi piace avere un globale che specifica un "livello di debug". Se il livello di debug è 0, non viene fornito alcun output extra. Quando è maggiore di 1, viene fornito l'output di debug, con più verbosità a numeri maggiori.

Mi piacerebbe anche configurarlo in modo che le procedure vengano eseguite e assumere un livello 0, se non avessi avuto modo di definirlo. Qualcosa come:?.. (Dove defined? è la magia non so come fare

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

ho guardato attraverso la sintesi di forme in The Scheme Programming Language, 4th Edition L'unico che ho visto come una possibilità era identifier? Ha fatto . non funziona

sto usando SISC 1.16.6 (sostiene R5RS compliance) e Chez Petite Scheme v8 (sostiene il rispetto R6RS)

EDIT ho provato avvolgendo eval con un guard come:

(guard (x (else #f)) (eval 'debug-level)) 

Poiché 'debug-level è quotato, può essere valutato e passato a eval. Quindi, quando eval prova a valutarlo, si verificherà un errore, che speravo che lo guard catturasse. Non è stato così.

EDIT 2 mi sono reso conto che volevo avvolgere il debug di tracciare in una procedura separata e che il file che definisce tale procedura può anche definire debug-level il valore predefinito è 0. Le ragioni per l'utilizzo di una procedura separata sono per abbassare il numero di linee nelle procedure che funzionano e anche per consentire il reindirizzamento dell'output di debug se necessario.

risposta

4

Questo è totalmente all'altezza dell'implementazione da fornire e sembra che la maggior parte delle implementazioni non lo forniscano in modo soddisfacente.

Nello schema SISC, sembra che è possibile utilizzare GETPROP a questo effetto, ma ambienti non aggiornano automaticamente oh, guarda, c'è questa cosa chiamata INTERAZIONE-ambiente che è possibile utilizzare:

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

Ma funziona solo al massimo livello.

 
#;> (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 

Per Chez voi hanno TOP-LEVEL-BOUND? e l'interazione-AMBIENTE nuovo.

+0

Grazie. Temevo che la risposta non sarebbe stata ampiamente condivisibile, che sarebbe stata una novità in R6RS o specifica di implementazione. +1, ma ho intenzione di lasciare che questa risposta invecchi un po ', per vedere se qualche idea migliore viene pubblicata prima di accettarla come corretta. –

1

Per eseguire il backup un po ', il problema con una funzione defined? è che se si scrive

(defined? debug-level) 

Scheme tenterà di valutare debug-level, che naturalmente è un errore dal momento che non è definito. Tale modulo dovrebbe essere implementato internamente dal compilatore/interprete come caso speciale.

Tale modulo speciale non fa parte dello standard R5RS (a meno che non lo abbia perso, per favore, double-check). Quindi per quanto riguarda gli schemi R5RS sei sfortunato a meno che non trovi uno Schema che lo implementa come un'estensione non standard.

+0

Non stavo chiedendo una funzione 'defined?' perché, come dici tu, una funzione non funzionava. Ma una funzione non funzionerebbe per 'if' neanche, eppure lo schema ha' if'. In altri workd, cercando una forma speciale o un altro modo per raggiungere i risultati. (Macro forse?) –

+1

Sicuro. Quello che stavo cercando di dire è che questo dovrebbe essere uno dei moduli incorporati forniti dal linguaggio, come 'if', e la specifica (almeno R5RS) non sembra includerne una. –

2

Soluzione robusta ma praticabile per R5RS. Usa l'abilità spesso trascurata/dimenticata della let-syntax per ridefinire le parole chiave. questo è goffo perché l'intero file è avvolto in una let-syntax e perché aggiunge un sovraccarico a ogni definizione. Io uso un elenco associativo per ricordare le definizioni, una tabella hash sarebbe una scelta migliore.

(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)) 
) 

stampe

#t 
#f 

basso in racket: un modulo viene utilizzato per ridefinire definire per memorizzare ogni simbolo e la definizione in un elenco chiamato define-list. La macro definita? guarda in questa lista per vedere se il tempo è o meno il simbolo è stato definito.

(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 è appena definito? apparentemente: http://www.delorie.com/gnu/docs/guile/guile_289.html

+1

Racket ha gli strumenti di riflessione per fare qualcosa del genere, ma cose del genere (inclusi 'interaction-environment', qualunque cosa Guile faccia, ecc.) Sono sempre soluzioni traballanti, che soffrono in un modo o nell'altro. –

+0

+1 per la soluzione portatile. –