2010-07-16 26 views
7

我希望能够在访问它之前测试一个变量是否被定义。如何在引用它之前测试变量是否已定义?

我喜欢指定一个“调试级别”的全局。如果调试级别为0,则不会给出额外的输出。当大于1时,给出调试输出,数字越大则越冗长。

我也想设置它,以便程序运行,并假设一个0级,如果我没有得到定义它。喜欢的东西:。(其中defined?是神奇的,我不知道该怎么办

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

我走过的形式汇总看着The Scheme Programming Language, 4th Edition,我看到的可能性是identifier?唯一一个它没有。不行

我使用SISC 1.16.6(声称R5RS规范)和切斯娇小方案V8(声称R6RS达标)

编辑我试着用guard包装eval,如:

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

由于'debug-level被引用,因此可以评估并传递给eval。然后,当eval试图评估它时,会发生错误,我希望guard会被捕获。它没有。

编辑2我发现我想换行调试跟踪到一个单独的程序,并且定义该程序也可以以0的原因默认定义debug-level用于使用一个单独的过程中的文件是降低过程中可以工作的行数,并且还允许在需要时重定向调试输出。

回答

4

这完全取决于实现提供,它看起来像大多数实现不令人满意地提供它。

在SISC方案,它看起来像你可以使用GETPROP这种效果,但环境不会自动更新哦,你看,有这个东西叫做交互环境,你可以使用:

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

但它只适用于顶层。

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

对于Chez,您再次有TOP-LEVEL-BOUND?和INTERACTION-ENVIRONMENT。对于R5RS

+0

谢谢。我很害怕,答案不会是广泛的便携,这将是无论是在R6RS或实施具体的新的东西。 +1,但我打算让这个答案的年龄了一下,看看是否有更好的想法得到接受是正确的之前公布。 – 2010-07-16 21:02:46

1

要备份一位,defined?功能的问题是,如果你写

(defined? debug-level) 

计划将试图评估debug-level,这当然是因为它没有定义的错误。作为一种特殊情况,这种形式必须由编译器/解释器在内部执行。

这种特殊形式不是R5RS标准的一部分(除非我错过了它,请double-check)。因此,对于R5RS方案,除非您找到将此项作为非标准扩展实现的方案,否则您运气不佳。

+0

我不是问一个函数定义''因为,如你所说,一个功能是行不通的?但是一个函数也不适用于'if',但是scheme有'if'。在其他工作中,寻找特殊形式或其他方式来实现结果。 (宏也许?) – 2010-07-16 19:32:52

+1

当然。我想说的是,这必须是该语言提供了内置的形式,如'if'之一,并且规范(R5RS至少)似乎不包括一个。 – 2010-07-16 19:37:25

2

笨重,但可行的解决方案。使用let-syntax经常忽略/遗忘的能力来重新定义关键字。这是笨重的,因为你的整个文件被封装在一个let语法中,并且因为它给每个定义增加了一些开销。我使用关联列表来记忆定义,散列表将是一个选择。

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

打印

#t 
#f 

下面在球拍:一个模块用于重新定义定义存储每个符号和定义在称为定义列表列表。宏定义了吗?在这个列表中查看是否天气符号已被定义。

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

在guile中它只是被定义的吗?显然: http://www.delorie.com/gnu/docs/guile/guile_289.html

+1

球拍确实有反射工具做这样的事情,但这样的事情(包括'交互environment',无论狡诈呢,等)总是摇摇欲坠一种解决方案,遭受这样或那样的。 – 2010-07-17 22:29:18

+0

适用于便携式解决方案。 – 2010-07-19 15:43:20

相关问题