【发布时间】: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