增量宏定义是否可行?

时间:2010-05-01 04:54:42

标签: lisp scheme macros

我经常发现以下类型的增量定义很有用:

(define (foo) (display "bar"))
(foo)
;prints bar
(define foo (let ((bar foo))
              (lambda ()
                (display "foo")
                (bar))))

(foo)
;prints foobar

如何使用宏预先形成此类增量定义? 我无法让let-syntax提供相同的功能。

目前我使用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)

如果我错过了一个更好的方法,请告诉我。

5 个答案:

答案 0 :(得分:3)

通过宏执行此操作,您将成为创建地球上最难维护软件的途径。

编辑:在Common Lisp中,它是可能的。我不记得我曾经见过它在源代码中使用过。

在Common Lisp社区中,向函数或宏添加行为通常称为“建议”或“建议”。一些“建议”工具还具有建议宏的能力。

答案 1 :(得分:3)

我认为你不能用宏来做这样的事情。我也没有看到任何尝试。

请注意,宏不只是一些具有额外魔力的功能!宏完全不同。

也许你正在寻找Common Lisp中方法组合的东西?

答案 2 :(得分:2)

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上运行 - 这是一个良好的事物。也可以在模块中做类似的事情,但是如果你要这样做,你也可以使用程序宏(aka syntax-case宏),并在语法级别绑定一个标识符,并且设置!' - 它的价值来扩展它。仍然不是一个好主意,仍然可以导致眼睛流血,但有些人喜欢伤害自己...

(哦,顺便说一句 - 即使这样做仍然与所讨论的宏是否卫生完全无关。)

答案 3 :(得分:1)

我认为你可以通过使用不卫生的宏来实现这一点,我相信PLT Scheme支持这些宏。然后你将使用与常规函数完全相同的机制,因为宏将是在S表达式上运行的常规函数​​。

我不知道如何使用卫生宏来做这件事,但我很惊讶你不能 - 我会考虑在PLT邮件列表上询问。

答案 4 :(得分:0)

let*怎么办?

(define foobar
    (let* ((foo (lambda () (display "foo")))
           (bar (lambda () (foo) (display "bar"))) )
            bar))