我是Lisp的新手,我想将时间输出打印到文件(/tmp/foo.txt)中,所以我定义了一个关于时间的包装函数,如下所示:
(defun my-time(form)
(lisp::with-open-file (*trace-output* "/tmp/foo.txt"
:direction :output
:if-exists :append
:if-does-not-exist :create)
(time(form))))
(defun test(n)
(dotimes (i n) (format t "this is test ~a.~&" i)))
但是,当我跑(我的时间(测试2))时,会出现以下错误: 错误:使用arguments()调用未定义的函数FORM。
我做这个测试时没关系:(时间(测试2))
有人可以给我一些线索吗?
答案 0 :(得分:5)
您的(test 2)
表单在my-time
运行之前正在执行,因为函数的参数在进入函数之前始终会被评估。因此,在编写时,它将无法正常工作。但仅凭这一点并没有给你任何错误,只是错误的测量。
接下来,my-time
函数内部会发生什么:您运行表单form
。除非你事先定义了它,否则没有这样的形式 - 所以你得到一个错误。
每次Lisp遇到一个列表时,它都会尝试执行它。 List,其中第一个元素是表示名为 form 的函数或宏的名称的符号。即使您使用引号也不会取消此规则:quote
表单将被执行并返回其内容。
(form element ...)
;^^^^ - from namespace for functions
Common Lisp中有两个名称空间。带有可执行符号和变量名称空间的命名空间。在my-time
内部,您有变量form
,但此符号位于变量的名称空间中,而不是函数。因此,您会收到错误。
有两种方法可以解决您的问题:
lambda
包裹您的表单,然后使用my-time
在funcall
内执行。您可以使用与您的功能非常相似的宏:
(defmacro my-time(&body body)
`(with-open-file (*trace-output*
"/tmp/foo.txt"
:direction :output
:if-exists :append
:if-does-not-exist :create)
(time (progn ,@body))))
这将有效(如果你很幸运,目录“temp”存在; - )
首先,定义my-time
:
(defun my-time (form)
(with-open-file (*trace-output*
"/tmp/foo.txt"
:direction :output
:if-exists :append
:if-does-not-exist :create)
(time (funcall form))))
然后试试吧:
(my-time (lambda nil (time 2)))
作品。我的“foo.txt”文件现在已经充满了统计数据。