我的任务是使用 宏 计算 a 和 b 之间所有素数的列表do-primes 然后使用自定义代码打印它们。
说(do-primes(n 5 15)(鲜线)(原则))应该打印4行:
这是我的代码:
{
"bool": {
"should": [
{
"term": {
"online-booking": false
}
},
{
"bool": {
"must": [
{
"term": {
"online-booking": true
}
},
{
"nested": {
"path": "partnerData",
"query": {
"query_string": {
"query": "Dimmi",
"fields": [
"partnerData.partnerName"
]
}
}
}
}
]
}
}
]
}
}
但是,当我运行代码时出现此错误:
EVAL:(FRESH-LINE)不是函数名称;尝试使用符号
如何使这段代码正常运行?
答案 0 :(得分:5)
请记住:宏转换代码。
如果你有像
这样的代码(do-primes (n 5 15)
(fresh-line)
(princ n))
您应该问自己的第一个问题是:转换后的代码应该是什么样的?然后将实际运行的代码。
一旦你知道目标代码应该是什么样子,就可以编写翻译。
Lisp有类似的宏:dolist
和dotimes
。你可以检查他们的宏扩展。上面有几种方法可以实现。一种是为身体使用功能和闭合。通常,在Lisp中,虽然我希望它们扩展到一些低级代码进行循环迭代。
在伪代码表示法中,更高级的编码方法是:
for n from n below/upto 15
when is-prime (n)
do fresh-line () and princ (n)
因此do-primes
宏需要扩展为类似的代码 - 但是Lisp代码。许多其他方法也是可能的。
您的代码
(defmacro do-primes ((var startv endv) &body body)
`(my-func ,startv ,endv)
`(,@body))
您的宏有两个子表单。为什么?计算第一个表格然后返回到无处。结果将被垃圾收集,因为它没有被使用。
第二种形式
`(,@body)`
将计算,返回值将是返回的代码。这样没有意义。括号不对语句进行分组,也没有迭代。
答案 1 :(得分:2)
宏可能非常棘手。这就是为什么当你尝试调试它们时,你应该做的第一件事就是宏扩展它们。 (在Emacs中有一个快捷方式:C-c RET
)您还可以在REPL中键入(macroexpand [your macro usage here])
。在您的情况下,您应键入:
(macroexpand '(do-primes (n 5 15) (fresh-line) (princ n)))
产生((FRESH-LINE) (PRINC N))
。
由于(fresh-line)
不是函数名称 - fresh-line
,因此您会收到该错误。
答案 2 :(得分:1)