如何在便携式方案中编写照应宏?

时间:2014-09-13 15:06:09

标签: macros scheme

我正在探索Scheme宏,但我一直无法找到一种编写照应宏的便携方式。

我正在尝试编写each-it宏,这样代码:

(each-it (list 1 2 3)
  (display it))

扩展到:

(for-each (lambda (it)
            (display it))
          (list 1 2 3))

我已经用syntax-rules编写了一个宏,但是当我尝试使用它时,这会给我一个关于未定义标识符的错误。

(define-syntax each-it
  (syntax-rules ()
    ((each-it lst body)
     (for-each (lambda (it) body)
               lst))))

This SO question提及define-syntax-parameter,这似乎只是Racket。 This blog post给出了一些Scheme代码示例,但代码示例不能在R5RS模式下在DrRacket中运行(我认为它是方括号?)。

R4RS has an interesting macro appendix但它不存在于R5RS中,我不知道我是否可以依赖它。

我能以完全可移植的方式编写each-it宏吗?如果没有,用于编写宏的最广泛的宏系统功能是什么?

2 个答案:

答案 0 :(得分:4)

这应该是可移植的,至少在R6RS:

(define-syntax each-it
  (lambda (x)
    (syntax-case x ()
      ((_ lst body)
       (with-syntax ((it (datum->syntax x 'it)))
         #'(for-each (lambda (it) body) lst))))))

答案 1 :(得分:3)

是的,您可以以便携方式编写它,假设R6RS足够便携。 (同样不能说R7RS,目前只有syntax-rules,并且不清楚将包含在大语言中的内容,或何时会发生。)请参阅uselpa,了解如何做到这一点。 / p>

那我为什么要写另一个答案呢?因为实际上这样做是个坏主意。一个不好的想法,不是在一些模糊的学术意义上,对大多数现实世界的代码都无关紧要 - 在某种意义上可能会在以后咬你。我知道“纸张”使它看起来令人生畏,但至少阅读了你见过的另一个SO问题中提到的the paper的前两部分。具体来说,第1.2节显示了您将要运行的问题。然后,第2节展示了如何“正确”地执行它,这使得编写扩展为使用宏的宏变得繁琐。在这一点上,采取“只是保持卫生”是有吸引力的,但在第2节结束时,你会明白为什么这也不起作用。

除非您有语法参数或类似内容,否则IMO的底线是不会这样做。也许唯一的例外(可能是你的情况)是当你想要自己使用宏时,你永远不会将它提供给其他人。

相关问题