我经常发现以下类型的增量定义很有用:
(define (foo) (display "bar"))
(foo)
;prints bar
(define foo (let ((bar foo))
(lambda ()
(display "foo")
(bar))))
(foo)
;prints foobar如何使用宏来执行这种类型的增量定义?我无法让let语法提供相同的功能。
目前我使用plt方案,但也希望在不同的lisp实现中看到答案。
编辑:
我天真地想要做以下事情:
(define-syntax foo
(syntax-rules ()
((_) (display "bar"))))
(define-syntax foo
(let-syntax ((old-foo (syntax-rules () ((_) (foo)))))
(syntax-rules ()
((_) (begin
(display "foo")
(old-foo))))))将朴素宏转换为工作的plt方案宏:
(require-for-syntax scheme/base)
(define-syntax foo
(syntax-rules ()
[(foo) (display "bar")]))
(define-syntax foo
(let ([old (syntax-local-value #'foo)])
(lambda (stx)
#`(begin #,((syntax-rules ()
[(_) (begin (display "foo"))]) stx)
#,(old #'(_))))))
(foo)如果我错过了更好的方法,请让我知道。
发布于 2010-05-04 09:03:37
FWIW (这绝对不是很多,因为这是一个用脚练习目标的练习),下面是你如何在PLT Scheme中使用卫生的syntax-rules宏做到这一点:
(define-syntax foo
(syntax-rules ()
[(foo x) (list 'x '= x)]))
(define-syntax foo
(let ([old (syntax-local-value #'foo)])
(compose (syntax-rules ()
[(_ x ...) (list 'begin x ... 'end)])
old)))
(printf ">>> ~s\n" (foo (+ 1 2)))这不能在模块中工作,只能在REPL上工作--这是一件好事。在模块中也可以做类似的事情,但如果你想这样做,你也可以使用过程化的宏(也就是syntax-case宏),在语法级别绑定一个标识符,并使用‘`set!’值来扩展它。仍然不是一个好主意,仍然可以导致眼睛出血,但有些人喜欢伤害自己…
(哦,顺便说一句--即使这样做也完全与所讨论的宏是否卫生无关。)
发布于 2010-05-01 16:12:03
有了宏,你就可以创建世界上最难维护的软件了。
编辑:在Common Lisp中这是可能的。我不记得我曾经在源代码中见过它。
在Common Lisp社区中,向函数或宏添加行为通常称为“建议”或“建议”。一些“建议”工具也具有建议宏的能力。
发布于 2010-05-01 18:12:34
我不认为你可以用宏做这样的事情。我也看不出有什么值得尝试的。
请注意,宏不仅仅是一些具有额外魔力的函数!宏是完全不同的东西。
也许你正在寻找类似于Common Lisp中的方法组合?
https://stackoverflow.com/questions/2748940
复制相似问题