Macros 使用语法规则引入命名变量

Macros 使用语法规则引入命名变量,macros,scheme,chicken-scheme,syntax-rules,Macros,Scheme,Chicken Scheme,Syntax Rules,我正试图用语法规则编写一个超小型的面向对象系统,主要是为了学习它。无论如何,我试图引入一个“this”变量。以下是我希望能够做到的: (oo-class Counter ( (attr value 0) (attr skip 1) ) ( (method (next) (set! value (+ value skip)) value) (method (nextnext) (this 'next) (th

我正试图用语法规则编写一个超小型的面向对象系统,主要是为了学习它。无论如何,我试图引入一个“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中尝试过这一点,在R5RS模式中也尝试过DrRacket(其他模式对此抱怨不已)

下面是整个文件。只需“csi object.scm”就可以在鸡肉上运行它

我还尝试使用let语法,并使用(this)作为语法说明符来引用(this)变量。但是,据我所知,它不允许我在语法重写中直接访问自己生成的变量

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

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

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

(let ((else #f))
  (cond (else (display "hi!\n")))) ;; Will not print
现在,您可以编写一个非常繁琐的宏,在扩展中的任何可能位置和嵌套级别匹配
这个
,但这永远不会完成,它也不会按词汇嵌套

你可以用大家都知道的东西来做你想做的事情,但这完全是对语法规则的攻击和滥用,而且在跨实现的模块中(例如,在CHICKEN中,我们有一个意外地“破坏”了这个特性),它不起作用(一致地)

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

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

在csi中,您可以使用
,x(宏调用)
,但它只能进行一级扩展


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

谢谢您的回复!我发现了一些有趣的事情。。。。1) 虽然我的代码没有发布,但是如果我做了你的“报价”技巧来查看输出,然后复制/粘贴结果,它确实有效!我不知道这是计划的标准部分还是鸡肉计划的怪异之处。2) 我利用了这个优势。我做了一个“let”将引号技巧的结果分配给一个变量,然后对结果进行“eval”。维奥拉,成功了!这是一个有效的实现:这个
eval
技巧有效,因为所有语法信息都已被剥离。在您的原始代码中有
(let((this#f))…)
;它将被转换为类似于
(let((this123#f))…
,并且宏定义中出现的任何其他
this
将被转换为
this123
,而用户提供的
this
将被转换为(比如)
this456
。但是,当您评估引用的输出时,所有这些
this
标识符都将被“展平”(去掉语法信息),因此将被折叠为相同的标识符。一般来说,这不是一个好主意:)