在 Racket 中,我可以重新定义“if”形式并让其他派生形式自动遵循其新语义吗?
In Racket, can I redefine the form `if` and have other derived forms automatically follow its new semantics?
在自定义 Racket 语言中,我想更改核心形式 if
以及扩展到它的其他形式(例如 and
和 cond
的行为).
当然,我可以重新定义这些形式中的每一个,但这似乎是多余的。例如,这是一个示例,其中修改后的 if
期望其每个参数都包含在一个列表中。宏 and
在这里被明确地重新定义。
;; my-lang.rkt
#lang racket/base
(require (for-syntax racket/base))
(provide #%module-begin #%datum #%app
list
(rename-out [car-if if] [car-and and]))
(define-syntax (car-if stx)
(syntax-case stx ()
[(_ c t f) #'(if (car c) t f)]))
(define-syntax (car-and stx) ; this seems redundant
(syntax-case stx ()
[(_) #'#t]
[(_ x) #'x]
[(_ x xs ...) #'(car-if x (car-and xs ...) x)]))
#lang s-exp "my-lang.rkt"
(if (list #f) (list 2) (list 3)) ; => (3)
(and (list #f) (list 2)) ; => (#f)
是否有一种更简单的方法来重新定义这些形式,方法是 将我对 if
的新定义注入 if
到 racket/base
提供的现有定义中?
答案是否定的
让我们考虑一下形式 and
。它被定义为一个宏(某处)。
它看起来像:
#lang mumble
(define-syntax (and stx)
(syntax-case stx ()
[(_and) #'#t]
[(_and e) #'e]
[(_and e1 e2) #'(let ([t e1]) (if t e2 #f))]
[(_and e1 e2 e ...) #'(let ([t e1]) (if t (and e2 e ...)))]
[_ (raise-syntax-error 'and "bad syntax" stx)]))
由于Racket宏系统是"referentially transparent"
标识符使用标准词法范围规则进行绑定。那是
扩展中的 if
绑定到模块中的 if
,其中
宏已定义。关键是宏编写器不
需要担心任何用户重新定义扩展中使用的任何标识符。
改变上述 and
宏行为的唯一方法是
更改使用的 if
。所以只有当你有权访问定义时
"mumble" 个,您可以更改使用的 if
个。在标准的情况下
球拍 and
没有用户可以更改定义。
简而言之,由于宏系统的设计,答案是"no"
在自定义 Racket 语言中,我想更改核心形式 if
以及扩展到它的其他形式(例如 and
和 cond
的行为).
当然,我可以重新定义这些形式中的每一个,但这似乎是多余的。例如,这是一个示例,其中修改后的 if
期望其每个参数都包含在一个列表中。宏 and
在这里被明确地重新定义。
;; my-lang.rkt
#lang racket/base
(require (for-syntax racket/base))
(provide #%module-begin #%datum #%app
list
(rename-out [car-if if] [car-and and]))
(define-syntax (car-if stx)
(syntax-case stx ()
[(_ c t f) #'(if (car c) t f)]))
(define-syntax (car-and stx) ; this seems redundant
(syntax-case stx ()
[(_) #'#t]
[(_ x) #'x]
[(_ x xs ...) #'(car-if x (car-and xs ...) x)]))
#lang s-exp "my-lang.rkt"
(if (list #f) (list 2) (list 3)) ; => (3)
(and (list #f) (list 2)) ; => (#f)
是否有一种更简单的方法来重新定义这些形式,方法是 将我对 if
的新定义注入 if
到 racket/base
提供的现有定义中?
答案是否定的
让我们考虑一下形式 and
。它被定义为一个宏(某处)。
它看起来像:
#lang mumble
(define-syntax (and stx)
(syntax-case stx ()
[(_and) #'#t]
[(_and e) #'e]
[(_and e1 e2) #'(let ([t e1]) (if t e2 #f))]
[(_and e1 e2 e ...) #'(let ([t e1]) (if t (and e2 e ...)))]
[_ (raise-syntax-error 'and "bad syntax" stx)]))
由于Racket宏系统是"referentially transparent"
标识符使用标准词法范围规则进行绑定。那是
扩展中的 if
绑定到模块中的 if
,其中
宏已定义。关键是宏编写器不
需要担心任何用户重新定义扩展中使用的任何标识符。
改变上述 and
宏行为的唯一方法是
更改使用的 if
。所以只有当你有权访问定义时
"mumble" 个,您可以更改使用的 if
个。在标准的情况下
球拍 and
没有用户可以更改定义。
简而言之,由于宏系统的设计,答案是"no"