【问题标题】:In Racket, can I redefine the form `if` and have other derived forms automatically follow its new semantics?在 Racket 中,我可以重新定义“if”形式并让其他派生形式自动遵循其新语义吗?
【发布时间】:2019-09-14 17:01:45
【问题描述】:

在自定义 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 的新定义注入racket/base 提供的现有定义中?

【问题讨论】:

    标签: macros racket


    【解决方案1】:

    答案是否定的。

    让我们考虑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 宏系统是“参照透明的”
    标识符使用标准的词法范围规则进行绑定。那是 扩展中的if 绑定到模块中的if,其中 宏被定义。关键是宏作者没有 需要担心任何用户重新定义扩展中使用的任何标识符。

    改变上述and 宏行为的唯一方法是 更改使用的if。因此,只有您有权访问定义 “mumble”,您可以更改使用的if。在标准的情况下 Racket and 没有用户可以更改定义。

    简而言之,由于宏观系统的设计,答案是否定的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2012-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多