2013-02-09 53 views

回答

8

更換firstonly(或其他充滿詩意的名字)函數,你想使你的主張的一個先決條件:

(defn only [x] {:pre [(nil? (next x))]} (first x)) 

(only [1]) 
=> 1 

(only [1 2]) 
=> AssertionError Assert failed: (nil? (next x)) user/only (NO_SOURCE_FILE:1) 
+0

是的。這個答案。 – dfreeman 2013-02-13 22:52:37

+0

'(僅[1 nil])'說明了此解決方案中的一個錯誤。 – 2013-12-15 12:23:54

+1

@AlexBaranosky謹慎解釋? '(next [1 nil])'是''(nil)'和'(nil?'(nil))'是'false'。因此,'(僅[1 nil])'會根據需要拋出斷言錯誤。 – 2013-12-16 15:15:35

1

我不能立即想到一個很好的簡潔,慣用的方式來做到這一點。

選項1是沒有一個,因爲這是一個奇怪的情況。如果你知道應該只有一個元素,爲什麼它首先在列表中?

選項2的是,有一次,有人會來告訴關閉沒有看到它:)

這就是說,在你的情況我可能會寫類似:

(let [[item & rest] alist] 
    (if (nil? rest) 
    (throw (IllegalArgumentException. "Expected a single-element list")) 
    item)) 

可能更簡單一點,您也可以只做(count alist)並確保它只有一個項目。但是,上面的代碼具有很好的屬性,它不會強制評估超出列表的頭部,但取決於您可能不需要擔心的用例。

+1

我不喜歡'count'方法,因爲它不適用於長序列或無限序列。 – 2013-12-15 12:24:30

3

這將炸燬對集合比一個元素其他任何東西。懶惰的seqs也能很好地工作。

(defn only 
"Gives the sole element of a sequence" 
[coll] 
(if (seq (rest coll)) 
    (throw (RuntimeException. "should have precisely one item, but had at least 2")) 
    (if (seq coll) 
    (first coll) 
    (throw (RuntimeException. "should have precisely one item, but had 0"))))) 
+0

+1 - 這是一個很好的答案,因爲除了避免使用'count',它可以同時處理''(僅nil)'和'(only(sorted-map 1:a 2:b))''。 – 2017-04-13 02:34:48

0

The Tupelo library具有被定義爲芯完整性檢查此功能,允許人們從長度爲1的矢量/列表「解包」的標量值,並記錄預期的結果。定義本身很簡單:

(defn only 
    "(only coll) 
    Ensures that a sequence is of length=1, and returns the only value present. 
    Throws an exception if the length of the sequence is not one. 
    Note that, for a length-1 sequence S, (first S), (last S) and (only S) are equivalent." 
    [coll] 
    (let [coll-seq (seq coll) 
     num-items (count coll-seq)] 
    (when-not (= 1 num-items) 
     (throw (IllegalArgumentException. (str "only: num-items must=1; num-items=" num-items)))) 
    (clojure.core/first coll-seq))) 

您可以找到SuchWow library和其他地方類似的功能。

相關問題