抑制Lisp中打印函数的输出

抑制Lisp中打印函数的输出,lisp,common-lisp,Lisp,Common Lisp,我是Lisp的新手,我遇到了一个印刷问题。我有一个功能,可以打印到标准输出(除其他外)。然后我想通过另一个函数运行这个函数,在这个函数中,它仍然运行相同的函数,但是没有任何东西被打印到标准输出 这里有一个简单的例子来说明我的意思。我描述了以下两个功能: (defun does-printing() (print "This goes to standard output.")) (defun run-other-function (function) (funcall function

我是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.
;;#的运球开始于2014-10-05 21:49:49。
#
[7] >(运行其他函数#'进行打印)
“这将转到标准输出。”
[8] >(运球)
;; #的运球于2014-10-05 21:50:09完成。

请注意,打印功能仍然打印到标准输出。当通过运行其他函数运行打印时,它希望能够以某种方式抑制此打印。在寻找解决方案时,我尝试了许多不同的措辞,但没有达到我想要的效果。

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

注意,您不应该将其设置为NIL,因为在这种情况下,print将显示type error

(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
另一个选择(可能更好)是使用,所以您可以捕获这个输出值,或者忽略它。我认为它更好,因为如果我们不需要它,为什么要做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"
但我认为宏在这种情况下会更加通用和惯用(可能我错了)


因此,您可以在
中调用许多具有抑制输出的表单

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


如果广播流没有组件流,则所有输出都将被丢弃。上面将
*标准输出*
绑定到这样的流。这不会占用任何数据,而且是可移植的。

只需添加一个可选参数“print output”即可进行打印。在某些情况下,我确实喜欢此解决方案,但它无法满足我的需要。我一直在为MySeltf编写一个基本的单元测试结构,只是为了练习该语言,所以我不必担心为每个可能的打印输入可选参数。我使用了您给出的第一个输出到字符串的示例,因为我只需要将它放在一个函数中。我仍在试图破译所有的片段,但现在它能满足我的需要。非常感谢。
(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-open-stream (*standard-output* (make-broadcast-stream))
  (call-some-function-1)
  ...
  (call-some-function-n))