压倒"这" Racket中的标识符宏

时间:2016-06-03 17:40:21

标签: macros scheme racket override

我在Racket中制作了自己的原型OO系统,使用"这个"方法。一切都很好,但不幸的是它阻止了Racket的本地系统使用"这个"。

这是我想做的事情:

(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)))))

我试图做的一件事就是重命名上面的"这个"宏观是" newthis"并按如下方式创建一个帮助宏:

(define-syntax (this stx)
  (syntax-case stx ()
    (this #'(if (null? (self)) oldthis newthis))))

但是在这两种情况下,Racket都会抛出错误,因为我正在使用" oldthis"在课堂背景之外。我如何仅仅参考旧的"这个"宏没有扩展它并抛出错误?或者,更广泛地说,我怎样才能使我的"这个"宏代表旧的"这" (self)为null时的宏?

提前致谢!

编辑:这是一些使用"这个"正确:

(define Foo (new))
(void (@ Foo 'name "Foo")
      (@ Foo 'method (lambda () (@ this 'name))))

然后你可以运行Foo"方法"通过调用

((@ Foo 'method))

这给出了正确的结果" Foo"

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

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

并运行

(define foo (make-object foo%))
(send foo displayself)

我总是得到(),因为"这个" return(self)和(self)在其闭包中有一个值" self"目前为空。我想要做的是检查(self)是否为null,如果是,则委托内置"这个"宏。

EDIT2:

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

我接近的一件事就是把它放在(eval' 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的命名空间参数,我可以引用旧的"这个"没有使用我的OO库对程序做任何假设,除了它可以访问球拍语言。

1 个答案:

答案 0 :(得分:0)

您应该可以直接使用rename-in执行此操作。以下面的代码为例:

#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相同的绑定。这是必要的,因为我们立即将该绑定与(define this 42)

相关联

接下来,我们使用一种方法定义foo%对象:get-me,它只返回当前对象this(或具体为old-this

最后,我们定义了一个名为foo%的新bar,并致电get-me。如您所见,它会像您期望的那样返回bar对象。

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