微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

宏和变量的常见 LIsp 问题

如何解决宏和变量的常见 LIsp 问题

我有一个作业,需要使用 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 时,print 语句会在涉及变量 i 时抛出错误。出于某种原因,我无法使用具有值的宏变量 i 打印它,但它似乎想要认为尚未设置的全局变量 i。我收到错误

- EVAL: variable I has no value

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

我将如何解决这些问题?

解决方法

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

(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
  • 尝试计算代码以外的结果

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。