Macros 压倒一切;这";球拍中的标识符宏
我在Racket中创建了自己的原型OO系统,它使用“this”作为方法。一切都很好,但不幸的是它阻止了Racket的原生类系统使用“this” 以下是我想做的: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
(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)