コードのある時点で、リストには要素が1つしかないことがわかっているので、
(first alist)
ただし、リストに複数の要素が含まれている場合は、誤った状態を警告するためにコードを壊したいと思います。Clojureでそれを達成するための慣用的な方法は何ですか?
コードのある時点で、リストには要素が1つしかないことがわかっているので、
(first alist)
ただし、リストに複数の要素が含まれている場合は、誤った状態を警告するためにコードを壊したいと思います。Clojureでそれを達成するための慣用的な方法は何ですか?
first
アサーションを作成する前提条件を持つ(または他の詩的な名前の)関数に置き換えonly
ます。
(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)
これは、1つの要素以外のコレクションで爆発します。怠惰なシーケンスでも問題なく動作します。
(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")))))
これを行うための簡潔で慣用的な方法をすぐに思いつくことはできません。
オプション1は、これが少し奇妙な状況であるため、1つがないことです。正確に1つの要素があるはずだとわかっているのなら、そもそもなぜそれがリストにあるのでしょうか。
オプション2は、1つあり、誰かがやって来て、それが表示されないことを告げるというものです:)
そうは言っても、あなたの状況では、私はおそらく次のようなものを書くでしょう:
(let [[item & rest] alist]
(if (nil? rest)
(throw (IllegalArgumentException. "Expected a single-element list"))
item))
おそらくもっと簡単に、あなたは(count alist)
それがちょうど1つのアイテムを持っていることを確認することもできます。ただし、上記のコードには、リストの先頭を超えて評価を強制しないという優れた特性がありますが、ユースケースによっては問題にならない場合があります。
Tupeloライブラリには、コアの健全性チェックとして定義されたこの関数があり、長さ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ライブラリやその他の場所にあります。