【问题标题】:Macro and array crossing宏和数组交叉
【发布时间】:2011-01-16 16:27:48
【问题描述】:

我遇到了 lisp 宏的问题。我想创建一个宏 根据数组生成一个switch case。

下面是生成switch-case的代码:

(defun split-elem(val)
  `(,(car val) ',(cdr val)))

(defmacro generate-switch-case (var opts)
  `(case ,var
     ,(mapcar #'split-elem opts)))

我可以用这样的代码来使用它:

(generate-switch-case onevar ((a . A) (b . B)))

但是当我尝试做这样的事情时:

(defparameter *operators* '((+ . OPERATOR-PLUS)
                            (- . OPERATOR-MINUS)
                            (/ . OPERATOR-DIVIDE)
                            (= . OPERATOR-EQUAL)
                            (* . OPERATOR-MULT)))

(defmacro tokenize (data ops)
  (let ((sym (string->list data)))
    (mapcan (lambda (x) (generate-switch-case x ops)) sym)))

(tokenize data *operators*)

我收到此错误:*** - MAPCAR: A proper list must not end with OPS,但我不明白为什么。

当我打印ops 的类型时,我得到SYMBOL 我期待CONS,这是否相关?

另外,对于我的函数tokenize,lambda 被评估了多少次(或宏展开)?

谢谢。

【问题讨论】:

  • 使用macroexpand-1 查看宏生成的代码。
  • 你想做什么?什么是data,你想让tokenize返回什么?
  • [13]> (macroexpand-1 '(generate-switch-case + ((+ . "PLUS")))) (CASE + ((+ '"PLUS"))) ;
  • tokenize 应该被视为函数(现在,对不起,数据是一个字符列表,我想生成代码来测试每个字符,看看它是否必须被替换为东西:)

标签: macros common-lisp


【解决方案1】:

这毫无意义。您尝试使用宏,功能就足够了。

你想要的是类似这样的:

(defun tokenize (data ops)
    (mapcar (lambda (d)
               (cdr (assoc d ops)))
            (string->list data)))

CASE 是一个需要一堆固定子句的宏。它不接受在运行时计算的子句。如果列表数据应该驱动计算,那么使用 ASSOC 之类的函数。

GENERATE-SWITCH-CASE 也是一个奇怪的名字,因为宏是一个 switch case。

GENERATE-SWITCH-CASE 也确实需要一个列表作为第二个参数。但在 TOKENIZE 中,您使用符号 OPS 来调用它。请记住,宏使用 Lisp 源代码进行计算。

接下来,也没有涉及数组。 Lisp 有数组,但在你的例子中没有。

典型建议:

  1. 如果您想编写宏,请三思。把它写成一个函数。

  2. 如果你还想写宏,转到1。

【讨论】:

  • 感谢您的回复。如果我想写一个宏,那是为了训练自己,因为我刚刚开始学习 lisp :)
  • @Thomas:有一些很好的介绍解释了在 Common Lisp 中编写宏。查看 Peter Seibel 的 Practical Common Lisp(免费在线 HTML)和 Paul Graham 的 On Lisp(免费 PDF 版本)。尤其是后者详细解释了使用。
  • 我已经读过 lisp 的土地,我在 Seibel 的 :) 谢谢! (Paul Garham 的将是下一个)
猜你喜欢
  • 1970-01-01
  • 2013-08-24
  • 2019-12-21
  • 2021-08-05
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
相关资源
最近更新 更多