如何在引用变量之前测试它是否已定义?

发布于 2024-09-10 16:18:15 字数 987 浏览 4 评论 0原文

我希望能够在访问变量之前测试变量是否已定义。

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

我还想对其进行设置,以便程序能够运行,并假定级别为 0(如果我没有抽出时间来定义它)。像这样的东西:(在哪里定义?是我不知道该怎么做的魔法?

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

我已经浏览了Scheme 编程语言,第四版。我认为唯一可能的是 identifier ? 不起作用。

我使用的是 SISC 1.16.6(声称符合 R5RS)和 Chez Petite Scheme v8(声称符合 R6RS)

编辑我尝试包装 eval< /code> 与 guard 类似:

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

由于 'debug-level 被引用,因此可以对其进行评估并传递给 eval 然后当 . eval 尝试评估它,会发生错误,我希望 guard 能够捕获它,

EDIT 2 我意识到我想换行 。调试跟踪到一个单独的过程中,并且定义该过程的文件还可以定义默认值为 0 的调试级别。使用单独过程的原因是为了减少确实有效的过程,并且还允许在需要时重定向调试输出。

I would like to be able to test whether a variable is defined, prior to accessing it.

I like to have a global that specifies a "debug level". If debug level is 0, no extra output is given. When greater than 1, debug output is given, with more verbosity at greater numbers.

I also would like to set it up so that the procedures would run, and assume a level 0, if I had not gotten around to defining it. Something like: (where defined? is the magic I don't know how to do?

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

I have looked through the summary of forms in The Scheme Programming Language, 4th Edition. The only one that I saw as a possibility was identifier?. It did not work.

I'm using SISC 1.16.6 (claims R5RS compliance) and Chez Petite Scheme v8 (claims R6RS compliance)

EDIT I tried wrapping eval with a guard like:

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

Since 'debug-level is quoted it can be evaluated and passed to eval. Then when eval tries to evaluate it, an error would happen, which I hoped guard would catch. It didn't.

EDIT 2 I realized that I wanted to wrap the debug tracing into a seperate procedure and that the file that defines that procedure can also define debug-level with a default of 0. The reasons for using a seperate procedure are to lower the number of lines in the procedures that do work and also to allow the redirection of debug output if needed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

狠疯拽 2024-09-17 16:18:15

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

在 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? 和交互-再次是环境。

This is totally up to the implementation to provide, and it looks like most implementations don't satisfactorily provide it.

In SISC scheme, it looks like you can use GETPROP to this effect, but environments don't update automatically oh, look, there's this thing called INTERACTION-ENVIRONMENT that you can use:

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

But it only works on the top level.

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

For Chez you have TOP-LEVEL-BOUND? and INTERACTION-ENVIRONMENT again.

还给你自由 2024-09-17 16:18:15

R5RS 的笨重但可行的解决方案。使用 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))
  )

在racket中打印

#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

Clunky but workable solution for R5RS. Use the often neglect/forgotten ability of let-syntax to redefine keywords. this is clunky because your whole file is wrapped in a let-syntax and because it adds some overhead to each define. I use a associative list to remember definitions, a hash table would be a beter choice.

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

prints

#t
#f

Below in racket: a module is used to redefine define to store each symbol and definition in a list called define-list. The macro defined? looks in this list to see if weather or not the symbol has been defined.

(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 it is just defined? apparently:
http://www.delorie.com/gnu/docs/guile/guile_289.html

仅此而已 2024-09-17 16:18:15

稍微备份一下,define?函数的问题是,如果您编写

(defined? debug-level)

Scheme将尝试评估debug-level,这当然是一个错误,因为它是未定义。作为特殊情况,这种形式必须由编译器/解释器在内部实现。

这样的特殊形式并不是R5RS标准的一部分(除非我错过了,请仔细检查)。因此,对于 R5RS 方案,除非您找到一个将其实现为非标准扩展的方案,否则您就不走运了。

To back up a bit, the problem with a defined? function is that if you write

(defined? debug-level)

Scheme will attempt to evaluate debug-level, which of course is an error since it is not defined. Such a form would have to be implemented internally by the compiler/interpreter as a special case.

Such a special form is not part of the R5RS standard (unless I missed it, please double-check). So with regard to R5RS schemes you are out of luck unless you find a Scheme that implements this as a non-standard extension.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文