2012-12-11 63 views
12

我有一個clojure地圖。將其命名爲opts。我知道2種方式從這個地圖等,如果沒有鑰匙得到一些默認值獲取值:clojure地圖的默認值

(let [opts {} 
     title-1 (or (:title opts) "Default title") 
     title-2 (:title opts "Default title")] 
    (println title-1 title-2)) 

我看到了一些庫(奎爾,咒術)使用帶有or第一種方法。在我看來,第二種方法更簡潔,更清晰。第一種方法是否有優勢?
使用(or (:title opts) "Default value")的缺點是我們不能通過falsenil作爲值,在這種情況下總是使用默認值。

+2

您也可以使用'(get opts:title「Default title」)'。 – ponzao

+0

@ponzao這可能會更好,因爲如果map爲'nil','get'不會拋出'NullPointerException'。如果指定了它,它會返回'nil'或默認值。 –

+0

@IvanKoblik'(:title nil「Default」)'也可以正常工作。 –

回答

20

(or (:key hash) default)(:key hash default)之間的一個重要區別是,前者僅在需要時評估default。在後一種情況下,它總是被評估。因此,如果對default的評估很昂貴,則應使用or

當您的散列值包含布爾值上下文中的值時,另一個區別就會變得明顯。在這種情況下,(or (:key hash) default)將被評估爲default,而不是您期望的falsenil。與or表達式相反,(:key hash default)將產生正確的結果。作爲附註,在將nil作爲值存儲在散列中之前,請三思。

很好,那些是重要的區別。現在讓我們轉到次要的。

(or (:title opts) "Default title") 

由讀取器擴展到

;; Redacted for the sake of brevity. 
(let* [x (:title opts)] 
    (if x 
    x 
    "Default title")) 

可以說,它是低效率的,而不是簡單地評估

(:title opts "Default title") 

當然沒有任何基準它很難估計的差速度,但我相信它應該是邊緣的。

另一方面,乍一看(or (:key hash) :default)似乎更容易理解一個不熟悉(:key hash :default)習語的人。考慮來自其他語言的程序員。在Ruby中的實例來處理的哈希值的不存在的元素典型的做法是

val = hash[:key] || :default 

因此,第一表達可能更容易被其他人不習慣於某些Clojure的成語解析。

+2

我完全不同意你應該始終如一:每種風格偶爾都是必需的。如果默認表達式計算起來非常昂貴,或者當'nil'或'false'爲有效值時使用默認表達式,並且您需要區分「Nothing there」和「false or nil那裏」。 – amalloy

+0

@amalloy,感謝您的評論並指出重要的不同之處。我已經修改了答案。 – Jan