这是一个关于Clojure三个不同方面交叉的问题。
- 集合函数将
nil
视为空集合。例如,filter
、map
以及甚至assoc
都乐意接受nil
作为集合(coll)。
if
及继承宏(如when
、and
、or
等)将nil
视为假值。
empty?
将输入转换为seq
,这会导致不必要的分配。使用seq
而不是(not (empty? xs))
来检查非空性是惯用的。这常常是造成混淆的常见来源,因为(not (empty? xs))
的意图似乎比seq
更清晰。
话虽如此,我认为在应用程序中显式地将每个空集合表示为nil
可能是有用的,因为这样
(let [xs (get-non-empty-coll-or-nil)]
(if xs
(do-stuff-with xs)
(do-nothing)))
...比这个
(let [xs (get-possibly-empty-coll)]
(if (seq xs)
(do-stuff-with xs)
(do-nothing)))
这种方法的两个缺点是:
- 必须使用
(fnil conj [])
或(fnil conj #{})
而不是conj
来确保集合是向量或集合,因为将nil
加上元素会创建一个列表,而我几乎从不使用列表。
- 必须对所有进入系统的集合在边界上通过
not-empty
进行处理。
您觉得呢?