2010-07-16 20 views
7

Me gustaría poder probar si una variable está definida, antes de acceder a ella.¿Cómo compruebo si una variable está definida antes de hacer referencia a ella?

Me gusta tener un global que especifique un "nivel de depuración". Si el nivel de depuración es 0, no se da salida adicional. Cuando es mayor que 1, se proporciona una salida de depuración, con más detalle en números mayores.

También me gustaría configurarlo para que los procedimientos se ejecuten, y asumir un nivel 0, si no hubiera llegado a definirlo. Algo así como:?.. (Donde defined? es la magia no sé cómo hacer

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

He mirado a través del resumen de las formas en The Scheme Programming Language, 4th Edition El único que vi era como una posibilidad identifier? Se hizo . no funciona

estoy usando SISC 1.16.6 (reclamaciones R5RS cumplimiento) y V8 Chez Pequeño Esquema (reivindicaciones cumplimiento R6RS)

EDITAR he intentado envolver eval con un guard como:

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

Dado que 'debug-level se cita, se puede evaluar y pasar al eval. Entonces, cuando eval intente evaluarlo, se produciría un error, que esperaba guard atraparía. No fue así.

EDIT 2 me di cuenta que quería envolver el seguimiento de depuración en un procedimiento separado y que el archivo que define dicho procedimiento también puede definir debug-level con un valor predeterminado de 0. Las razones para el uso de un procedimiento particular son para bajar el número de líneas en los procedimientos que sí funcionan y también para permitir la redirección de la salida de depuración si es necesario.

Respuesta

4

Esto es totalmente hasta la puesta en práctica de proporcionar, y parece que la mayoría de las implementaciones no satisfactoria proporcionarla.

En el esquema SISC, parece que se puede utilizar GETPROP a este efecto, pero entornos no se actualizan automáticamente oh, mira, hay una cosa llamada interacción hombre-entorno que puede utilizar:

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

pero sólo funciona en el nivel superior.

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

Para Chez que tienen TOP-LEVEL-BOUND? y la interacción-AMBIENTE nuevo.

+0

Gracias. Temía que la respuesta no fuera ampliamente portable, que sería algo nuevo en R6RS o específico de implementación. +1, pero voy a dejar que esta respuesta envejezca un poco, para ver si se publican mejores ideas antes de aceptarlas como correctas. –

1

Para retroceder un poco, el problema con una función defined? es que si se escribe

(defined? debug-level) 

Esquema intentará evaluar debug-level, que por supuesto es un error ya que no está definido. Tal forma tendría que ser implementada internamente por el compilador/intérprete como un caso especial. una forma especial

Tal no es parte del estándar R5RS (a menos que me lo perdí, por favor double-check). Por lo tanto, con respecto a los esquemas R5RS no tiene suerte a menos que encuentre un Esquema que implemente esto como una extensión no estándar.

+0

No estaba pidiendo una función 'definida?' porque, como dices, una función no funcionaría. Pero una función no funcionaría para 'if' tampoco, y aún el esquema tiene' if'. En otros workds, buscando una forma especial u otra forma de lograr los resultados. (¿Macro tal vez?) –

+1

Claro. Lo que intentaba decir es que este debería ser uno de los formularios incorporados que proporciona el lenguaje, como 'si', y la especificación (al menos R5RS) no parece incluir uno. –

2

Clunky pero solución viable para R5RS. Use la capacidad a menudo olvidada/olvidada de la sintaxis de dejar para redefinir palabras clave. esto es torpe porque todo tu archivo está envuelto en una sintaxis let y porque agrega un poco de sobrecarga para cada definición. Utilizo una lista asociativa para recordar las definiciones, una tabla hash sería una opción de beter.

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

impresiones

#t 
#f 

continuación en la raqueta: un módulo se utiliza para definir redefinir para almacenar cada símbolo y definición de una lista llamada define-lista. ¿La macro definida? mira en esta lista para ver si el clima o el símbolo ha sido definido.

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

En guile se acaba de definir? aparentemente: http://www.delorie.com/gnu/docs/guile/guile_289.html

+1

Racket tiene las herramientas de reflexión para hacer algo como esto, pero tales cosas (incluyendo 'interaction-environment', lo que sea que Guile haga, etc.) son siempre un tipo de soluciones inestables, que sufren de una forma u otra. –

+0

+1 para la solución portátil. –

Cuestiones relacionadas