0

我正在尝试使用语法规则编写一个超小型的面向对象系统,主要是为了学习它。无论如何,我正在尝试引入一个“this”变量。这是我希望能够做到的:

(oo-class Counter 
    (
        (attr value 0)
        (attr skip 1)
    )
    (
        (method (next) (set! value (+ value skip)) value)
        (method (nextnext) (this 'next) (this 'next))
        (method (set-value newval) (set! value newval))
        (method (set-skip newskip) (set! skip newskip))
    )
)

(define c (Counter))
((c 'set-value) 23)
((c 'next))
((c 'nextnext))

除了“这个”之外,我可以让一切正常工作。似乎语法规则不允许变量引入。我以为我可以通过将其定义为语法规则中的文字之一来获得它,但这似乎不起作用。

下面是我的面向对象系统:

(define-syntax oo-class
    (syntax-rules (attr method this)
        (
            (oo-class class-name 
                ((attr attr-name initial-val) ...) 
                ((method (meth-name meth-arg ...) body ...) ...))
            (define class-name 
                (lambda () 
                    (letrec
                        (
                            (this #f)
                            (attr-name initial-val)
                            ...
                            (funcmap 
                                    (list 
                                        (cons (quote meth-name) (cons (lambda (meth-arg ...) body ...) '()))
                                        ...
                                    )
                            )
                        )
                        (set! this (lambda (methname)
                            (cadr (assoc methname funcmap))
                        ))
                        this
                    )
                )
            )
        )
    )
)

这适用于除 'nextnext 之外的所有内容,当它尝试引用“this”时会出错。

这是正确的方法吗?还有其他方法可以做到这一点吗?我承认这有点不卫生,但这至少不是指定文字的一部分吗?

我已经在 Chicken Scheme 和 DrRacket 中尝试过 R5RS 模式(其他模式抱怨“这个”)。

下面是整个文件。您可以使用“csi object.scm”在 Chicken 上运行它

https://gist.github.com/johnnyb/211e105882248e892fa485327039cc90

我还尝试使用 let-syntax 并使用 (this) 作为语法说明符来引用 (this) 变量。但是,据我所知,它并没有让我在语法重写中直接访问我自己制作的变量。

奖励问题:查看语法规则转换结果以进行调试的简单方法是什么?有没有办法让鸡肉(或其他东西)进行转换并吐出结果?我在 DrRacket 上尝试了一些东西,但它在 R5RS 模式下不起作用。

4

1 回答 1

1

我承认这有点不卫生,但这至少不是指定文字的一部分吗?

不,文字存在,因此您可以在关键字上进行字面匹配,例如子句中的the=>或 the 。它仍然是卫生的,因为如果or在词汇上绑定到某个值,则具有优先权:elsecond=>else

(let ((else #f))
  (cond (else (display "hi!\n")))) ;; Will not print

现在,您可以编写一个非常繁琐的宏,它匹配this扩展中任何可能的位置和嵌套级别,但这永远不会完整,而且它也不会在词法上嵌套。

可以使用已被称为Petrofsky 提取的方法来做您想做的事情,但这是对语法规则的彻底破解和滥用,并且在存在跨实现的模块时(始终)不起作用(例如,正是在 CHICKEN 中,我们曾抱怨我们不小心“破坏”了此功能)。

我的建议是编写一个语法规则宏,该宏在其输入中接受一个标识符,该标识符将绑定到当前对象,然后编写一个微不足道的不卫生宏,以硬编码标识符this作为输入调用另一个宏。

什么是查看用于调试的语法规则转换结果的简单方法?有没有办法让鸡肉(或其他东西)进行转换并吐出结果?我在 DrRacket 上尝试了一些东西,但它在 R5RS 模式下不起作用。

在 csi 中,您可以使用,x (macro-call),但它只会进行一级扩展。

在每个 Scheme 实现中起作用的一个常见技巧是更改宏定义以引用其输出。因此,它不是扩展到(foo)而是扩展到'(foo)。这样,您只需调用 REPL 中的宏并立即查看其结果。

于 2018-04-23T18:32:51.597 回答