無需功能,也不要使用def
在函數中,除非你明確打算「創建和實習生全局變量」(中def
文檔字符串)。合併地圖可以使用merge
完成。
(doto (merge ms) (SomeJavaClass/someStaticVoidMethod "some" "other" "stuff"))
編輯:因爲我的答案可能有關正確使用高清的誤解(見獅子座流星雨的評論):在函數中使用清晰度是不是一個好主意。我引用了文檔字符串來暗示使用def的全局效果,而這在你的函數中肯定是不希望的。
EDIT2:這裏有一些關於上面一行的更多解釋:doto總是返回它的第一個參數。如果它是可變的並且它之後的表達式將其修改爲副作用,則返回修改後的版本。然而,如果你只是想調用一個靜態方法(大概)有副作用而不修改第一個參數,那麼使用doto是正確的,因爲你可以依賴你的地圖的不變性。
由於您在尋求一種通用的慣用方法,並希望在您的靜態方法(或具有副作用的函數)不希望將期望的返回值作爲第一個參數時解決類似問題,因此可以始終這樣做:
(doto (merge ms) (#(SomeJavaClass/someStaticMethod "Some" "other" "stuff" %)))
現在,如果出於任何原因需要確保靜態方法永遠不會修改參數(如果它是一個可變的事情),使用let塊沒有幫助。這是因爲在let-block中,你將一個符號綁定到可變的東西上,並且你不會從符號中得到它的舊值。您需要事先創建一箇舊值的副本,通常通過調用它的構造函數並創建它的一個新實例。在REPL
例子:
(let [a (into-array [4 3 2 1]]
(java.util.Arrays/sort a)
a)
(first *1)
=> 1
;; now how to return the original thiing
(let [a (into-array [4 3 2 1])
a-copy (aclone a)]
(java.util.Arrays/sort a)
;; do some other ops on a, maybe invoke side-effects
a-copy)
(first *1)
=> 4
因此,如果首先讓塊產生你想要的結果,讓塊可以與多託這是一個幫助宏不會完全不是別的,創建替換讓你阻止。
(doto (into-array [4 3 2 1]) java.util.Arrays/sort)
(first *1)
=> 1
(macroexpand '(doto (into-array [4 3 2 1]) java.util.Arrays/sort))
=> (let* [G__7326 (into-array [4 3 2 1])] (java.util.Arrays/sort G__7326) G__7326)
既然你不是「做什麼」到您的合併地圖,名稱爲「多託」可能有些誤導,但希望我可以convice您保存的冗餘幾行代碼。
IIRC函數中最後一行的評估結果是返回值。 – m0skit0
您應該**從不**在函數內部使用'def'。不僅因爲你影響全局範圍,而且因爲Clojure在編譯期間爲'def'創建了變量 –
@ m0skit0它不是,因爲void方法返回nil。 –