macros - Lisp - 在宏中使用逗号(`,`)
问题描述
我正在练习用 Elisp 编写宏。老师建议我们将程序的宏部分包含在“quasiquote”中。
我想写一个宏“printCdrEach”来打印列表中cdr的每个元素(只是为了练习)
(defmacro print-cdr-each (first &rest rest)
`(while (not (null ,rest))
(eval (car ,rest))
(setq rest (cdr ,rest)))
)
(print-cdr-each 1 2 3 4) ; Expected Output 2 3 4
我不断收到错误“无效功能:2”。我确信编译器认为2
是一个函数。但是,我不确定如何修复此程序。
在不更改输入格式(printCdrEach x x x x)
的情况下,在我的程序中正确使用“,”以使其正常工作是什么?
解决方案
你应该尝试macroexpand-1
:
(macroexpand-1 '(print-cdr-each 1 2 3 4))
; ==> (while (not (null (2 3 4)))
; (eval (car (2 3 4)))
; (setq rest (cdr (2 3 4))))
; ==> t
- 表达式
(2 3 4)
无效。在 REPL 中尝试一下,你会得到eval: 1 is not a function name
- 您正在使用
rest
多次,因此如果它是一个表达式,它将被多次评估。
真的不需要宏:
(defun for-each (operation &rest elements)
(loop :for e :in elements
:do (funcall operation e)))
(for-each #'print 10 20)
10
20
; ==> nil
宏是语法糖。这意味着您应该能够说出
(print-cdr-each 1 2 3 4)
代码中应该扩展的内容。由于您将其作为宏执行,因此您可能希望将其扩展为静态:
(defmacro for-each (operation &rest elements)
`(progn ,@(loop :for e :in elements
:collect `(,operation ,e))))
(macroexpand-1 '(for-each print a b))
; ==> (progn (print a) (print b))
; ==> t
(let ((a 10) (b 20)) (for-each print a b))
10
20
; ==> 20
推荐阅读
- python - 代码中的错误。Scikit 图像,Spyder
- go - 如何以 Go 语法在模板中输出地图?
- apache-spark - “SparkSession”对象没有属性“textFile”
- javascript - 如何在javascript中解析包含数组的任意数学表达式
- django - 如何在 Django Rest Framework 中自定义 ManyToMany 字段的更新方法
- flutter - 如何创建一个可以被多个区域使用的 Widget 监听的单例 Stream
- python - Python:从midi文件中获取正确的开始和结束
- python - 在python循环中重命名数据框
- javascript - 如何在 P5 js 中使用 sin(a) 和距离从 A 调制到 B?
- twitter-bootstrap - 为什么我的导航栏没有向右对齐?