2016-06-26 40 views
5

我在clojure很新。我想用換行符打印每個列表項。我想是這樣的:如何在單獨的行clojure中打印每個列表項目?

user=> (def my-list '(1 2 3 4 5)) 
;; #'user/my-list 
user=> my-list 
;; (1 2 3 4 5) 
user=> (apply println my-list) 
;; 1 2 3 4 5 
;; nil 

但我想我的輸出必須是:

1 
2 
3 
4 
5 
nil 

誰能告訴我,我該怎麼做?謝謝。

回答

6

這種用例(爲序列中的每個成員執行一次副作用)是doseq的用途。用在這裏會像

(doseq [item my-list] 
    (println item)) 

請注意,這不會打印nil返回它。在REPL中使用它會看到所有打印表達式的返回值,但不會在例如作爲終端程序開始您的項目。

+0

好的。我得到了我的答案。謝謝。 @Magos –

14

如果你已經有了,你想申請的每一個項目在一個序列的功能,你可以使用run!而不是doseq更大的簡潔:

(run! println [1 2 3 4 5]) 
;; 1 
;; 2 
;; 3 
;; 4 
;; 5 
;;=> nil 

doseq時要執行的操作是非常有用的執行更復雜,而不僅僅是將單個函數應用於單個序列中的項目,但這裏run!工作得很好。

+0

太酷了!這似乎更好的方法。謝謝。 @Sam –

1

另一種策略是從列表中創建一個字符串,然後打印該字符串。

user> (defn unlines [coll] 
     (clojure.string/join \newline coll)) 
#'user/unlines 

user> (unlines [1 2 3 4 5]) 
"1\n2\n3\n4\n5" 

user> (println (unlines [1 2 3 4 5])) 
1 
2 
3 
4 
5 
nil 
+0

主要區別在於你打印的序列是懶惰的;比較'(run!println(range))'和'(println(unlines(range)))'。 –

+0

@SamEstep你是對的,它在一個無限的列表上不是很有用。在構建字符串之前必須先實現惰性序列。但總的來說,將邊界影響代碼限制在邊界上並不是一個壞的策略。返回String的函數比打印到控制檯的函數要可測試得多。 –

+0

同意。這只是特別需要完成什麼任務的問題。在打印五個以換行符分隔的已知項目的特殊情況下,我會說你的'unlines'解決方案更好。但是在更一般情況下反覆執行操作(可能涉及輸入或輸出或兩者),預先計算結果並不總是一種選擇。 –

相關問題