Macros 压倒一切;这";球拍中的标识符宏

Macros 压倒一切;这";球拍中的标识符宏,macros,scheme,racket,overriding,Macros,Scheme,Racket,Overriding,我在Racket中创建了自己的原型OO系统,它使用“this”作为方法。一切都很好,但不幸的是它阻止了Racket的原生类系统使用“this” 以下是我想做的: (require (only-in racket (this oldthis))) (define-syntax this (syntax-id-rules (set!) ((set! this ...) (void)) ((this a ...) ((self) a ...)) (this (if (nu

我在Racket中创建了自己的原型OO系统,它使用“this”作为方法。一切都很好,但不幸的是它阻止了Racket的原生类系统使用“this”

以下是我想做的:

(require (only-in racket (this oldthis)))

(define-syntax this
  (syntax-id-rules (set!)
    ((set! this ...) (void))
    ((this a ...) ((self) a ...))
    (this (if (null? (self)) oldthis (self)))))
我尝试过的一件事是将上面的“this”宏重命名为“newthis”,并按如下方式创建一个helper宏:

(define-syntax (this stx)
  (syntax-case stx ()
    (this #'(if (null? (self)) oldthis newthis))))
但在这两种情况下,Racket都会抛出一个错误,因为我在类上下文之外使用“oldthis”。如何仅引用旧的“this”宏而不展开它并抛出错误?或者,更广泛地说,当(self)为null时,如何使我的“this”宏委托给旧的“this”宏

提前谢谢

编辑:以下是一些正确使用“this”的代码:

(define Foo (new))
(void (@ Foo 'name "Foo")
      (@ Foo 'method (lambda () (@ this 'name))))
然后可以通过调用

((@ Foo 'method))
它给出了正确的结果“Foo”

但是,如果我使用Racket的分级系统:

(define foo%
  (class object%
    (super-new)
    (define/public (displayself)
      (displayln this))))

(define foo (make-object foo%))
(send foo displayself)
我总是得到(),因为“this”返回(self)并且(self)的闭包中有一个当前为空的值“self”。我要做的是检查(self)是否为null,如果为null,则委托给内置的“this”宏

编辑2:

看起来是在做我想做的事情。然而,当我尝试它时,我仍然会得到关于类上下文的相同错误。我认为这是因为#%top宏是由(real top.rest)调用的,而不是由real top自己调用的。然而,在我的例子中,oldthis会立即被调用并抛出错误。我不知道如何防止这种情况

我所做的一件事是将oldthis括在(eval'oldthis)中,但这只在当前名称空间中起作用。为了使它能够持续工作,我必须将oldthis与其他内容结合起来提供,这不仅难看而且容易出错,因为毫无戒心的图书馆用户不一定知道他们必须一直传递oldthis才能使任何东西正常工作。所以我不想这样做

已解决:

(define-syntax this
  (syntax-id-rules (set!)
    ((set! this ...) (void))
    ((this a ...) ((self) a ...))
    (this (if (null? (self)) (eval 'this (module->namespace 'racket)) (self)))))

通过提供racket语言作为eval的名称空间参数,我可以引用旧的“this”,而无需对使用我的OO库的程序做任何假设,除非它可以访问racket语言。

您应该可以直接使用
中重命名。以以下代码为例:

#lang racket

(require (rename-in racket [this old-this]))

(define this 42)

 (define foo%
  (class object%
    (super-new)
    (define/public (get-me)
      old-this)))

(define bar (new foo%))

(send bar get-me)
在这里,我们使用
rename in
导入
old this
以指向与Racket中的
this
相同的绑定。这是必需的,因为我们立即使用:
(定义此42)

接下来,我们用一个方法定义
foo%
对象:
get me
,它只返回当前对象的
this
(或者特别是
old this

最后,我们定义了一个名为
bar
的新
foo%
,并调用
get me
。正如您所看到的,它会像您所期望的那样返回bar对象


如果您返回了
this
,而不是原来的this,那么
get me
将返回42,因为定义的原因。同样,如果您将
this
的定义删除为
42
,那么
this
仍将绑定到类宏所期望的定义上。

您能给出一个示例吗“它阻止Racket的本机类系统使用它。”?这并不能完全回答我的问题。我已经在中使用了,它正在做同样的事情。我想知道的是如何设计一个引用oldthis而不抛出错误的宏(即它应该扩展到oldthis)