Suppressing output from a print function in Lisp
I am new to Lisp and I am facing a printing problem. I have one function that prints to standard output (by the way). Then I want to run this function through another function where it still works the same, but instead nothing is printed to standard output.
Here's a simple example of what I mean. I describe the following two functions:
(defun does-printing()
(print "This goes to standard output."))
(defun run-other-function (function)
(funcall function)
(values))
Here's an example of what happens when I run this,
;; 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.
Note that the print function still prints to standard output. He would like to somehow suppress this printing at startup - printing via run-other-function. I have tried many different ways of formulating my problem when looking for solutions, but nothing comes out of what I would like to do.
source to share
The simplest solution is to create an empty broadcast stream.
(with-open-stream (*standard-output* (make-broadcast-stream))
(call-some-function-1)
...
(call-some-function-n))
If there is no component stream in the broadcast stream, all output will be discarded. The above links *standard-output*
to such a thread. This does not override any data and is carried over.
source to share
You can just redirect your stdout to some place. For example in / dev / null if you have one on your operating system. This looks like a very idiomatic UNIX output.
Note that you should not set it to NIL, because it will display a type error when printing.
(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
Another option (and maybe better) is to use with-output-to-string
so you can capture that output value or just ignore it. I think it's better, because why do IO if we don't need it, and it should work on any OS.
(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)))
If you do this a lot, you can wrap it in a macro or even a function to use instead of 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"
But I think the macro would be more general and idiomatic for this case (I may be wrong).
(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))
This way you can call many forms in with-suppressed-output
.
source to share