profiling - 如何在 Common Lisp 中定义宏时间的包装器

标签 profiling common-lisp

我是 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))时,出现以下错误: 错误:使用参数 () 调用未定义的函数 FORM。

我做这个测试时没问题:(时间(测试2))

有人可以给我一些线索吗?

最佳答案

发生了什么

您的(test 2) 表单在my-time 运行之前执行,因为函数的参数始终在进入函数之前进行求值。因此,正如它所写的那样,它不会按您想要的方式工作。但仅此一点不会给您带来任何错误,只是测量不正确。

接下来,my-time 函数内部会发生什么:运行一个表单 form。除非您事先定义了它,否则不存在这样的形式 - 因此您会收到错误。

每次 Lisp 遇到一个列表时,它都会尝试执行它。列表,其第一个元素是一个符号,表示名为 form 的函数或宏的名称。即使您使用引用,它也不会取消此规则:quote 表单将被执行并返回其内容作为结果。

(form element ...)
;^^^^ - from namespace for functions

Common Lisp 中有两个命名空间。具有可执行符号的命名空间和变量的命名空间。在 my-time 内部,您有变量 form,但该符号位于变量的命名空间中,而不是函数的命名空间中。因此你会得到一个错误。

如何修复

有两种方法可以解决您的问题:

  • 使用宏;
  • 使用 lambda 封装您的表单,然后使用 funcallmy-time 内执行它。

涉及宏的解决方案

您可以使用与您的函数非常相似的宏:

(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”存在;-)

解决方案涉及函数

首先,定义我的时间:

(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”文件现在充满了统计数据。

关于profiling - 如何在 Common Lisp 中定义宏时间的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24467438/

相关文章:

ubuntu - VTUNE : Cannot display data

windows - 分析 Windows 进程长期 CPU 使用率的最佳方法

debugging - 如何在 lisp (sbcl) 中禁用警告

list - 在 Lisp 中替换列表小节的最惯用方法

c - prof 和 gprof 有什么区别?

WPF Performance Suite Visual Profiler 不起作用

c - 如何计算C中的内存消耗

lisp - 运行 Common Lisp 时遇到问题

clojure - 来自除 CL 之外的其他语言的 Clojure 功能概述

lisp - LISP编程语言如何读取文件和保存数据