4 ms·
> empty > Not to be confused with empty?, which returns whether or not a collection is empty, empty returns an empty collection that is the same type as its ar
by Anderkent 12y ago
> empty
> Not to be confused with empty?, which returns whether or not a collection is empty, empty returns an empty collection that is the same type as its argument:
No, actually, it returns an empty collection that is the same type as its argument OR NIL.
The 'or nil' is really important, and what makes `empty` really not that useful.
Say, for example, that I wanted to iterate over a generic collection, and modify each element recursively, while preserving the types. One would think this would work:
(defn map-recurse [coll f]
(if-not (coll? coll)
(f coll)
(into (empty coll) (map #(map-recurse % f) coll)))
Alas. You'll find that while maps are in theory lists of vector pair
(empty (first {:a 1})) => nil
So empty really isn't very useful at all. If you know the collection will be one of the types that it supports, you might as well just create the empty collection explicitly - you know what type it is, after all.
- gregschlom 12y ago> You'll find that while maps are in theory lists of vector pair They aren't. When you seq over a map you get a list of MapEntry, like so: (clojure.lang.MapEntry. :a 1) MapEntries aren't vectors, and while they can be destructured like vectors, you can't make empty instances of them. (empty) still is useful in a variety of cases. See for example this bug report that I've filled: http://dev.clojure.org/jira/browse/CLJ-1476 http://dev.clojure.org/jira/browse/CLJ-1476
- Anderkent 12y agouser=> (pr-str (seq {:a 1 :b 2})) "([:a 1] [:b 2])" user=> (vector? (first (seq {:a 1 :b 2}))) true It looks like a vector, it quacks like a vector...
- eddieplan9 12y agouser=> (doc vector?) ------------------------- clojure.core/vector? ([x]) Return true if x implements IPersistentVector nil So `MapEntry` implements `IPersistentVector`, but is not a vector. It does not make sense to have an empty `MapEntry`, so IMHO the behavior implemented is valid.
- Anderkent 12y ago'Hey, if I peek under the abstraction, it all makes sense'. Obviously. The code does what it's written to do. That doesn't make such leaky abstractions okay. `vector?` is, AFAIK, the way to check if something is a vector, and if empty doesn't work on some `vector?`s, then i can't trust it. empty mapentry returning nil is meh. If it returned an empty vector it'd be what you want 99% of the time.