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.

+3


source to share


2 answers


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.

+10


source


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

.

+2


source







All Articles