我希望能够在访问变量之前测试变量是否已定义。
我喜欢有一个指定“调试级别”的全局。如果调试级别为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)和Chez Petite Scheme v8(声称符合R6RS)
编辑我尝试用eval
包裹guard
,如:
(guard (x (else #f)) (eval 'debug-level))
自引用'debug-level
以来,可以对其进行评估并将其传递给eval
。然后,当eval
尝试评估它时,会发生错误,我希望guard
能够捕获。它没有。
编辑2 我意识到我想将调试跟踪包装成一个单独的过程,并且定义该过程的文件也可以定义debug-level
,默认值为0.原因使用单独的过程是为了降低工作过程中的行数,并允许在需要时重定向调试输出。
答案 0 :(得分:4)
这完全取决于提供的实现,看起来大多数实现都不能令人满意地提供它。
在SISC方案中,看起来你可以使用GETPROP来实现这种效果,但是环境不会自动更新哦,看,这个叫做INTERACTION-ENVIRONMENT的东西,你可以使用方法:
#;> (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。
答案 1 :(得分:2)
R5RS的笨重但可行的解决方案。使用let-syntax常常忽略/遗忘的功能来重新定义关键字。这很笨重,因为你的整个文件都包含在let-syntax中,因为它为每个定义增加了一些开销。我使用关联列表来记住定义,哈希表将是一个更好的选择。
(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
下面的球拍:一个模块用于重新定义define以将每个符号和定义存储在名为define-list的列表中。宏定义了吗?查看此列表以查看是否已定义天气符号。
(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)
在诡计中它只是定义了吗?显然: http://www.delorie.com/gnu/docs/guile/guile_289.html
答案 2 :(得分:1)
要备份一点,defined?
函数的问题是如果你写
(defined? debug-level)
Scheme会尝试评估debug-level
,这当然是一个错误,因为它没有定义。这样的表格必须由编译器/解释器在内部实现作为一种特殊情况。
这种特殊形式不属于R5RS标准(除非我错过了,请double-check)。所以关于R5RS方案,除非你找到一个将其作为非标准扩展实现的方案,否则你运气不好。