使用语法规则引入命名变量
Introducing a Named Variable with Syntax Rules
我正在尝试编写一个带有语法规则的超小型面向对象系统,主要是为了学习它。无论如何,我正在尝试引入一个 "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))
除了 "this",我可以让所有东西正常工作。似乎语法规则不允许引入变量。我以为我可以通过将它定义为语法规则中的文字之一来获得它,但这似乎不起作用。
下面是我的面向对象系统:
(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 模式下尝试过这个(其他模式会抱怨 "this")。
下面是整个文件。你可以 运行 它只需要 "csi object.scm"
https://gist.github.com/johnnyb/211e105882248e892fa485327039cc90
我也尝试过使用 let-syntax 并使用 (this) 作为语法说明符来引用 (this) 变量。但是,据我所知,它不允许我在语法重写中直接访问我自己创建的变量。
红利问题:查看用于调试的语法规则转换结果的简单方法是什么?有什么办法可以让鸡(或者别的东西)做改造,吐出来结果吗?我在 DrRacket 上尝试了一些东西,但它在 R5RS 模式下不起作用。
I recognize that this is slightly unhygienic, but isn't that at least part of the point of specifying literals?
不,存在文字,因此您可以按字面匹配关键字,例如 cond
子句中的 =>
或 else
。它仍然是卫生的,因为如果 =>
或 else
在词法上绑定到某个值,则它具有优先权:
(let ((else #f))
(cond (else (display "hi!\n")))) ;; Will not print
现在,您可以编写一个非常乏味的宏来匹配 this
在任何可能的位置和扩展中的嵌套级别,但这永远不会完成,并且它也不会在词法上嵌套。
它 可以使用我们不小心 "broke" 此功能而闻名的 Petrofsky extraction, but it's a total and utter hack and abuse of syntax-rules and it does not work (consistently) in the presence of modules across implementations (for example, exactly in CHICKEN we've had a complaint 来完成您正在尝试做的事情。
我的建议是编写一个语法规则宏,在其输入中接受一个标识符,该标识符将绑定到当前对象,然后编写一个简单的不卫生的宏,用硬编码标识符调用另一个宏 this
作为输入。
What is an easy way to see the result of a syntax-rules transformation for debugging? Is there some way to get chicken (or something else) to do the transformation and spit out the result? I tried some stuff on DrRacket, but it doesn't work in R5RS mode.
在csi中,可以使用,x (macro-call)
,但只会做一层展开。
适用于每个 Scheme 实现的一个常见技巧是更改宏定义以引用其输出。因此,它不会扩展到 (foo)
,而是扩展到 '(foo)
。这样,您只需在 REPL 中调用宏并立即查看其结果。
我正在尝试编写一个带有语法规则的超小型面向对象系统,主要是为了学习它。无论如何,我正在尝试引入一个 "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))
除了 "this",我可以让所有东西正常工作。似乎语法规则不允许引入变量。我以为我可以通过将它定义为语法规则中的文字之一来获得它,但这似乎不起作用。
下面是我的面向对象系统:
(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 模式下尝试过这个(其他模式会抱怨 "this")。
下面是整个文件。你可以 运行 它只需要 "csi object.scm"
https://gist.github.com/johnnyb/211e105882248e892fa485327039cc90
我也尝试过使用 let-syntax 并使用 (this) 作为语法说明符来引用 (this) 变量。但是,据我所知,它不允许我在语法重写中直接访问我自己创建的变量。
红利问题:查看用于调试的语法规则转换结果的简单方法是什么?有什么办法可以让鸡(或者别的东西)做改造,吐出来结果吗?我在 DrRacket 上尝试了一些东西,但它在 R5RS 模式下不起作用。
I recognize that this is slightly unhygienic, but isn't that at least part of the point of specifying literals?
不,存在文字,因此您可以按字面匹配关键字,例如 cond
子句中的 =>
或 else
。它仍然是卫生的,因为如果 =>
或 else
在词法上绑定到某个值,则它具有优先权:
(let ((else #f))
(cond (else (display "hi!\n")))) ;; Will not print
现在,您可以编写一个非常乏味的宏来匹配 this
在任何可能的位置和扩展中的嵌套级别,但这永远不会完成,并且它也不会在词法上嵌套。
它 可以使用我们不小心 "broke" 此功能而闻名的 Petrofsky extraction, but it's a total and utter hack and abuse of syntax-rules and it does not work (consistently) in the presence of modules across implementations (for example, exactly in CHICKEN we've had a complaint 来完成您正在尝试做的事情。
我的建议是编写一个语法规则宏,在其输入中接受一个标识符,该标识符将绑定到当前对象,然后编写一个简单的不卫生的宏,用硬编码标识符调用另一个宏 this
作为输入。
What is an easy way to see the result of a syntax-rules transformation for debugging? Is there some way to get chicken (or something else) to do the transformation and spit out the result? I tried some stuff on DrRacket, but it doesn't work in R5RS mode.
在csi中,可以使用,x (macro-call)
,但只会做一层展开。
适用于每个 Scheme 实现的一个常见技巧是更改宏定义以引用其输出。因此,它不会扩展到 (foo)
,而是扩展到 '(foo)
。这样,您只需在 REPL 中调用宏并立即查看其结果。