用宏运行函数

时间:2016-11-10 02:47:27

标签: common-lisp

我的任务是使用 计算 a b 之间所有素数的列表do-primes 然后使用自定义代码打印它们。

(do-primes(n 5 15)(鲜线)(原则))应该打印4行:

  1. 5
  2. 7
  3. 11
  4. 13
  5. 这是我的代码:

    {
        "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)不是函数名称;尝试使用符号

    如何使这段代码正常运行?

3 个答案:

答案 0 :(得分:5)

请记住:宏转换代码。

如果你有像

这样的代码
(do-primes (n 5 15)
 (fresh-line)
 (princ n))

您应该问自己的第一个问题是:转换后的代码应该是什么样的?然后将实际运行的代码。

一旦你知道目标代码应该是什么样子,就可以编写翻译。

Lisp有类似的宏:dolistdotimes。你可以检查他们的宏扩展。上面有几种方法可以实现。一种是为身体使用功能和闭合。通常,在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)

您应该查看此处的示例:

http://www.gigamonkeys.com/book/macros-defining-your-own.html

我想,它会解释你需要的一切。