增量宏定义可能吗?

发布于 2024-08-30 19:18:26 字数 1006 浏览 5 评论 0原文

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

(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)

如果我缺少更好的方法,请告诉我。

I often find the following type of incremental definition useful:

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

(foo)
;prints foobar

How do I preform this type of incremental definition with macros?
I could not get let-syntax to provide the same functionality.

Currently I use plt scheme, but would like to see answers in different lisp implementations as well.

Edit:

Naively I would want to do the following:

(define-syntax foo
  (syntax-rules ()
    ((_) (display "bar"))))

(define-syntax foo
  (let-syntax ((old-foo (syntax-rules () ((_) (foo)))))
    (syntax-rules ()
      ((_) (begin
             (display "foo")
             (old-foo))))))

Translation of naive macros to working plt scheme macros:

(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)

If I am missing a better method let me know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

十级心震 2024-09-06 19:18:26

我不认为你可以用宏来做这样的事情。我也不认为尝试有任何意义。

请注意,宏不仅仅是一些具有额外魔力的函数!宏是完全不同的东西。

也许您正在寻找类似 Common Lisp 中的方法组合之类的东西?

I do not think that you can do something like this with macros. I also do not see any point in trying.

Please note that macros are not just some functions with extra magic! Macros are something different altogether.

Perhaps you are looking for something like method combinations in Common Lisp?

源来凯始玺欢你 2024-09-06 19:18:26

通过宏的实现,您将能够创建世界上最难维护的软件。

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

在 Common Lisp 社区中,向函数或宏添加行为通常被称为“建议”或“建议”。一些“建议”工具还可以为宏提供建议。

With macros doing this you are on the way to create the hardest to maintain software on the planet.

Edit: in Common Lisp it is possible. I can't remember that I have ever seen it used in source code.

Adding behavior to functions or macros is often called 'advise' or 'advice' in the Common Lisp community. Some 'advise' tools have also the ability to advise macros.

一梦等七年七年为一梦 2024-09-06 19:18:26

FWIW(这绝对不是很多,因为这几乎是用脚进行目标练习的练习),以下是您在 PLT 方案中仅使用卫生 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 宏),其标识符绑定在语法级别并“设置!”其值以扩展它。仍然不是一个好主意,并且仍然会导致眼睛流血,但有些人喜欢伤害自己......

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

FWIW (and this is definitely not much, since this is pretty much an exercise in target practicing with your feet), here is how you would do this in PLT Scheme with only hygienic syntax-rules macros:

(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)))

This will not work inside a module, only on the REPL -- and that is a good thing. It is possible to do something similar in modules too, but if you're going for that, you can just as well use procedural macros (aka syntax-case macros), with an identifier that is bound at the syntax level and `set!'-ing its value to extend it. Still not a great idea, and can still lead to eyes bleeding, but some people like to hurt themselves...

(Oh, and BTW -- even doing this is still completely unrelated to whether the macros in question are hygienic or not.)

遥远的她 2024-09-06 19:18:26

我认为你可以通过使用不卫生的宏来实现这一点,我相信 PLT 方案支持这一点。然后,您将使用与常规函数完全相同的机制,因为宏将是碰巧对 S 表达式进行操作的常规函数​​。

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

I think you could get this by using unhygienic macros, which I believe PLT Scheme supports. Then you would use exactly the same mechanisms as with regular functions, since the macros would be regular functions that happened to operate on S-expressions.

I don't know how to do this with hygienic macros, but I'm quite surprised you can't - I would consider asking on a PLT mailing list.

爱已欠费 2024-09-06 19:18:26

let* 怎么样?

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

What about let*?

(define foobar
    (let* ((foo (lambda () (display "foo")))
           (bar (lambda () (foo) (display "bar"))) )
            bar))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文