抑制Lisp中print函数的输出

时间:2014-10-06 03:00:31

标签: lisp common-lisp

我是Lisp的新手,我遇到了打印问题。我有一个函数可以打印到标准输出(除其他外)。我想通过另一个函数运行此函数,它仍然运行相同但没有任何东西被打印到标准输出。

这是我的意思的一个简单例子。我有以下两个描述的功能:

(defun does-printing()
  (print "This goes to standard output."))

(defun run-other-function (function)
  (funcall function)
  (values))

这是我运行时会发生的运球,

;; Dribble of #<IO TERMINAL-STREAM> started on 2014-10-05 21:49:49.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"example.out">
[7]> (run-other-function #'does-printing)

"This goes to standard output." 

[8]> (dribble)
;; Dribble of #<IO TERMINAL-STREAM> finished on 2014-10-05 21:50:09.

请注意,打印功能仍会打印到标准输出。它希望能够通过run-other-function运行打印时以某种方式抑制此打印。在搜索解决方案时,我已经尝试了许多不同的措辞,但没有任何东西可以达到我想做的目的。

2 个答案:

答案 0 :(得分:10)

最简单的解决方案是创建一个空的广播流。

(with-open-stream (*standard-output* (make-broadcast-stream))
  (call-some-function-1)
  ...
  (call-some-function-n))

如果广播流没有组件流,则将丢弃所有输出。上面将*standard-output*绑定到这样的流。这不会消耗任何数据,而且是可移植的。

答案 1 :(得分:2)

您只需将标准输出重定向到某个地方即可。例如,如果您的操作系统中有一个,则进入/ dev / null。看起来非常惯用的UNIX方式输出抑制。

请注意,您不应将其设置为NIL,因为在这种情况下,print会发出信号类型错误。

(defun does-printing()
  (print "This goes to standard output."))

(defun run-other-function (function)
  (with-open-file (*standard-output*
                    "/dev/null"
                    :direction :output
                    :if-exists :supersede)
    (funcall function)
    (values)))

CL-USER> (run-other-function #'does-printing)
; No value

其他选项(可能更好)是使用with-output-to-string,因此您可以捕获此输出值或忽略它。认为它更好,因为如果我们不需要它,为什么要做IO,而且它必须适用于任何操作系统。

(defun run-other-function (function)
  (with-output-to-string (*standard-output*
                           (make-array '(0)
                                       :element-type 'base-char
                                       :fill-pointer 0 :adjustable t))
    (funcall function)
    (values)))

如果你做了很多,你可以把它包装成宏甚至功能,用来代替funcall。

(defun does-printing()
  (print "This goes to standard output.")
  "My result")

(defun funcall-with-no-output (fn)
  (with-output-to-string (*standard-output*
                            (make-array '(0)
                                        :element-type 'base-char
                                        :fill-pointer 0 :adjustable t))
                          (funcall fn)))

CL-USER> (funcall-with-no-output #'does-printing) 
"My result"

但是我认为宏对于这种情况会更普遍和惯用(可能是我错了)。

(defmacro with-suppressed-output (&body body)
  `(with-output-to-string (*standard-output*
                            (make-array '(0)
                                        :element-type 'base-char
                                        :fill-pointer 0 :adjustable t))
   ,@body))

因此,您可以在with-suppressed-output中调用多个表单。