2014-10-06 61 views
3

我對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在運行do-printing時以某種方式抑制此打印。我在尋找解決方案時嘗試了許多不同的問題措辭,但沒有得到我想要做的事情。

+0

如何將可選參數「打印輸出」添加到打印? – 2014-10-06 05:40:07

+0

我確實喜歡這種解決方案的某些情況,但它不適合我的需求。我一直在爲myseltfjust編寫一個基本的單元測試結構,以便使用該語言進行一些練習,所以我不必擔心爲每個潛在打印添加可選參數。 – Nyles 2014-10-06 06:44:26

回答

10

最簡單的解決方案是創建一個空的廣播流。

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

如果廣播流沒有分量流,所有的輸出將被丟棄。以上將*standard-output*綁定到這樣的流。這不涉及任何數據,並且是便攜式的。

+0

這是一個優雅的解決方案,謝謝。 – Nyles 2014-10-06 07:13:35

2

您可以將您的標準輸出重定向到某個地方。例如,如果您的操作系統中有一個,則將其放入/ dev/null。它看起來像非常習慣性的UNIX方式輸出抑制。

請注意,您不應將其設置爲NIL,因爲在這種情況下,打印將發出信號類型錯誤。

(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許多表格。

+0

我用了第一個帶輸出到字符串的例子,因爲我只需要將它放在一個函數中。我仍然試圖破譯所有的部分,但它現在適合我的需求。謝謝。 – Nyles 2014-10-06 07:04:29