【问题标题】:Common LIsp issue with Macros and variables宏和变量的常见 LIsp 问题
【发布时间】:2021-04-18 00:50:16
【问题描述】:

我有一个需要使用 lisp 编写脚本的任务。我在传递变量时遇到问题

这里是代码。后续问题:

(defmacro while (test &rest bodies)
   `(do ()
        ((not ,test))
        ,@ bodies)
) 
(defmacro += (var inc)
    `(print (eval var))
    ;(setf (eval var) (+ (eval var) inc))
)

(defmacro iterate (i begin end inc &rest others)
    (setf i begin)
    
    (while (<= i (eval end))
        ;(dolist (item others)
        ;    (eval item)
        ;)
       
        (print (list 'two i (eval end)))
        (+= (eval end) 1)
        (setf i (+ i inc))
    )
)

(setf n 5)
(iterate i 1 n 1
    (print (list 'one i))
    (+= n 1)
)

第一个问题在于将语句传递给迭代宏。当我尝试运行注释掉的 dolist 时,当涉及到变量 i 时,print 语句将引发错误。由于某种原因,我无法使用具有值的宏变量 i 打印它,但它似乎希望默认为尚未设置的全局变量 i。我得到了错误:

- EVAL: variable I has no value

第二个问题是当我调用“+=”宏时。 iterate 宏中 end 的值是 5,通过使用设置为 5 的变量 N 传递给宏,但是,当我使用行“(+=(eval)将它传递给“+=”宏时结束)1)“我无法让它传递价值。我尝试删除“(+ =(eval end)1)”行中的eval,当我尝试在“+ =”宏中使用“(print(eval var))”打印它时,出现错误 - EVAL: 变量 END 没有值

我将如何解决这些问题?

【问题讨论】:

  • 您的 ITERATE 宏错误。它应该生成代码,但它不会。那么也没有理由使用 EVAL。
  • 一个好的经验法则是:'如果你使用eval,你就犯了一个错误'。 种情况eval是合理的,但它们根本不常见。

标签: lisp common-lisp


【解决方案1】:

您的第一个宏基本上是正确的。它生成代码。

(defmacro while (test &body body)
  `(do ()
       ((not ,test))
     ,@body))

你可以通过一个例子来检查它。我们使用示例代码扩展宏。函数MACROEXPAND-1 仅将顶级宏扩展一次。您需要将代码传递给函数MACROEXPAND-1

CL-USER 1 > (macroexpand-1 '(while (< i 10)
                              (print i)
                              (incf i)))
(DO NIL               ; NIL is the same as ()
    ((NOT (< I 10)))
  (PRINT I)
  (INCF I))
T
 

生成的代码是一个DO 循环。就像预期的那样。

因此我们可以使用您的宏:

CL-USER 2 > (let ((i 5))
              (while (< i 10)
                (print i)
                (incf i)))

5 
6 
7 
8 
9 
NIL

你的其他宏应该是这样的

  • 他们应该生成代码
  • 示例的宏扩展应该显示正确的生成代码
  • 生成的代码应该可以工作

您的宏不应该

  • 正在使用EVAL
  • 尝试计算代码以外的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多