Variables 如何知道球拍变量是否已定义
如果在racket语言中定义了变量或没有定义变量,您如何能有不同的行为?有几种方法可以做到这一点。但我怀疑这些都不是您想要的,因此我只提供指向函数的指针(并解释每个函数的问题):Variables 如何知道球拍变量是否已定义,variables,racket,defined,Variables,Racket,Defined,如果在racket语言中定义了变量或没有定义变量,您如何能有不同的行为?有几种方法可以做到这一点。但我怀疑这些都不是您想要的,因此我只提供指向函数的指针(并解释每个函数的问题): 是一个从某个命名空间检索顶级变量值的函数。不过,这仅对REPL交互和REPL代码有用,因为模块中定义的代码无论如何都不会使用这些东西。换句话说,您可以使用此函数(以及相应的名称空间设置变量值!)获取值(如果有)并进行设置,但这些值的唯一用途是在模块中本身不存在的代码中。换言之,使用此功能就像保留一个将符号映射到值的哈希
名称空间设置变量值!
)获取值(如果有)并进行设置,但这些值的唯一用途是在模块中本身不存在的代码中。换言之,使用此功能就像保留一个将符号映射到值的哈希表一样,只是在REPL上更方便一些,因为您只需键入名称最后两个选项更有用,但它们不是新手级别的宏,这就是为什么我怀疑你问错了问题。为了澄清,您可以使用它们编写一种
defined?
特殊表单,检查是否定义了某个名称,但这个问题将由宏根据代码的其余部分来回答,因此询问它并不是真正有用的。如果您想在其他动态语言中使用类似谓词的代码类型,那么最好的方法是重新定义#%top
以进行某种查找(哈希表或全局命名空间),而不是抛出编译错误,这与显式使用哈希表的区别主要是表面上的(同样,这不是一件新手的事情)。首先,阅读Eli的答案。然后,根据Eli的回答,您可以通过以下方式实现定义的?
宏:
#lang racket
; The macro
(define-syntax (defined? stx)
(syntax-case stx ()
[(_ id)
(with-syntax ([v (identifier-binding #'id)])
#''v)]))
; Tests
(define x 3)
(if (defined? x) 'defined 'not-defined) ; -> defined
(let ([y 4])
(if (defined? y) 'defined 'not-defined)) ; -> defined
(if (defined? z) 'defined 'not-defined) ; -> not-defined
它适用于这种基本情况,但有一个问题:如果z
未定义,则认为已定义并使用其值的if
分支将引发编译时错误,因为正常的if
在运行时(动态)检查其条件值:
所以,您可能需要一个if定义的宏,它在编译时(而不是在运行时)告诉if
的哪个分支:
#lang racket
; The macro
(define-syntax (if-defined stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([where (identifier-binding #'id)])
(if where #'iftrue #'iffalse))]))
; Tests
(if-defined z (list z) 'not-defined) ; -> not-defined
(if-defined t (void) (define t 5))
t ; -> 5
(define x 3)
(if-defined x (void) (define x 6))
x ; -> 3
你到底是什么意思?您是否试图在某个地方使用未定义的变量?我无法回答您的问题。请看。对于只在REPL中工作的东西,您也可以简单地捕获exn:fail:contract:variable?
异常。是的,但这不太适合新手使用,因为(a)您需要用异常捕获代码包装每个顶级交互,一旦捕获,就无法“跳回”将异常位置与其他值绑定,因此您唯一能做的就是中止交互。
#lang racket
; The macro
(define-syntax (if-defined stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([where (identifier-binding #'id)])
(if where #'iftrue #'iffalse))]))
; Tests
(if-defined z (list z) 'not-defined) ; -> not-defined
(if-defined t (void) (define t 5))
t ; -> 5
(define x 3)
(if-defined x (void) (define x 6))
x ; -> 3