【发布时间】:2015-04-30 17:01:22
【问题描述】:
我正在尝试格式化任意表达式,比如(+ 2 3),同时,它的结果是5。
我有以下几点:
(defun expr-and-result (expr)
(format t "~a returns ~a~%" expr (eval expr)))
CL-USER> (expr-and-result '(+ 2 3))
(+ 2 3) returns 5
虽然使用eval是一件简单的事情,但我很好奇如果没有它是否可以实现这种效果(因为我听说很多要避免使用eval)。
我知道引用参数是必要的,因为否则给定的表达式将作为调用expr-and-result 的第一步进行评估,并且只有它的结果可以在expr-and-result 中使用。因此,任何可能的解决方案都需要引用输入,对吧?
我对宏进行了一些思考,但我觉得这是我正在寻找的错误方法。
编辑:我的意图是构建一个简单的测试套件,例如:
(progn
(mapcar #'expr-and-result
'((= (my-remainder 7 3) 1)
(= (my-remainder 7 3) 2)))
'end-of-tests)
Outputs:
(= (MY-REMAINDER 7 3) 1) returns T
(= (MY-REMAINDER 7 3) 2) returns NIL
END-OF-TESTS
阅读 Paulo 的评论后,似乎eval 是我所用的最短和最干净的解决方案。
【问题讨论】:
-
这取决于您打算如何使用它。如果您正在开发一个详细的调试宏,那么您应该生成
(format ...)表达式,引用第一个参数而不是第二个参数。如果这是用于 REPL 或某些解释器,那很好。eval的编译替代方案是(funcall (compile nil `(lambda () ,expr))),但除非你真的想观察编译副作用或多次执行expr,否则没有必要这样做。 -
@PauloMadeira 感谢您的评论,我的目的是创建一个简洁的测试套件,用于将函数输出与预期结果进行比较。 (我编辑了我的问题)。生成
format表达式听起来有点矫枉过正,但我觉得这将是一个比 eval 更灵活的解决方案。 -
不要重新发明轮子:cliki.net/test%20framework
-
有很多轮子可供选择!
标签: common-lisp eval