在 Racket 中,我可以重新定义“if”形式并让其他派生形式自动遵循其新语义吗?

In Racket, can I redefine the form `if` and have other derived forms automatically follow its new semantics?

在自定义 Racket 语言中,我想更改核心形式 if 以及扩展到它的其他形式(例如 andcond 的行为).

当然,我可以重新定义这些形式中的每一个,但这似乎是多余的。例如,这是一个示例,其中修改后的 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 的新定义注入 ifracket/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"