【问题标题】:How do I map a macro across a list in Scheme?如何在 Scheme 中的列表中映射宏?
【发布时间】:2011-02-08 01:30:12
【问题描述】:

我有一个 Scheme 宏和一个长列表,我想将宏映射到整个列表中,就像它是一个函数一样。如何使用 R5RS 做到这一点?

宏接受几个参数:

(mac a b c d)

列表有

(define my-list ((a1 b1 c1 d1)
                 (a2 b2 c2 d2)
                 ...
                 (an bn cn dn)))

我想要这个:

(begin
   (mac a1 b1 c1 d2)
   (mac a2 b2 c2 d2)
   ...
   (mac an bn cn dn))

(顺便说一句,如您所见,我也想拼接参数列表)

【问题讨论】:

  • 我认为让您的问题更具体可能会有所帮助。
  • 什么是 a1 b1 ...?它们是原子的吗?他们是代码吗?在不了解更多数据的情况下,宏 z5H 可能有最好的答案。
  • 没有限制 a1 b1 ... 是什么。可以是原子,可以是列表,等等……

标签: macros scheme


【解决方案1】:

扩展 z5h 对使用 eval 的回答,下面的方法展示了如果在使用的 R5RS 版本中实现交互环境,如何编写 map-macro 宏:

(define test-list '((1 2 3 4)
                    (5 6 7 8)))

;Or if your version of scheme implments interaction-environment then:
(define-syntax trade
  (syntax-rules ()
    ((_ a b c d) (display (list b a d c)))))

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;Careful this is not really mapping. More like combined map and apply.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(define-syntax map-macro
  (syntax-rules ()
    ((_ mac ls) (let ((mac-list (map (lambda (lst) (cons 'trade lst)) ls)))
                          (eval 
                           `(begin
                              ,@mac-list)
                           (interaction-environment))))
                        ))

(map-macro trade test-list)
;outputs: (2 1 4 3)(6 5 8 7)

所以最后一次 map-macro 调用会评估以下内容:

最终从 (map-macro trade test-list) 得到评估的是:

(begin
  (trade 1 2 3 4)
  (trade 5 6 7 8))

这不是一张地图,但我相信它确实回答了你的问题。

【讨论】:

  • 所以这基本上意味着我不能选择编写一个“map-syntax”宏,它会迭代地(在宏本身中)扩展,直到 mac 为列表的所有成员扩展? (当然,我必须在宏中直接传递列表,而不是在变量中!)
  • 如果您在首选版本的 R5RS 方案中有交互环境,则可以有效地编写地图宏。在 R5RS 规范中交互环境是可选的。它确实存在于 DrScheme 或任何新名称中。我编辑了我的答案,以给出一个 map-macro 宏的示例。
【解决方案2】:

句法扩展扩展为 评估开始时的核心表格 (编译或解释之前) 通过语法扩展器。 ——戴维格,“ 方案编程语言:

宏对语法进行操作。这发生在编译或执行之前。它为您提供了另一种编写相同代码的方式。

函数对变量和值(可能是列表、原子、数字等)进行操作,当函数被调用时,它们的值是已知的。

所以映射宏没有意义。您要求调用很久以前已经发生的事情(宏扩展)。

如果您需要一些东西来为您编写代码并在运行时对其进行评估,那么可能是您需要eval 的情况之一。

【讨论】:

  • 我相信他希望在编译之前扩展宏(对吗?)。我不确定 Scheme,但我在 Common Lisp 中使用 defmacro 做了很多事情(defmacro 中的代码将使用许多其他函数来转换 S 表达式(甚至使用全局哈希表!))。一个宏会定义几个函数...
【解决方案3】:

想要什么

(map (lambda (l) (mac (car l) (caar l) (caaar l) (caaaar l))) mylist)

工作?

【讨论】:

  • 宏接受可变参数,所以上面的解决方法会报错。
  • 我不明白为什么这意味着你会得到一个错误。您是说 my-list 中的列表可能具有不同的长度吗?
  • @Jay Korninek 宏可能会操纵 a1 b1 内部的内容......因为我认为我们不能假设它们是原子的。
  • 如果宏不接受那么多参数,(caaaar l) 可能会发出错误信号。我想要一些非常通用的东西......
猜你喜欢
  • 2012-09-07
  • 1970-01-01
  • 2017-07-30
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
相关资源
最近更新 更多