Fork me on GitHub
#datascript
<
2022-05-24
>
phronmophobic00:05:25

To me, the main reason to avoiding having an attribute exist with a nil value is that it often leads to a data model with 3 states: • entity has :my/attribute and its value is x • entity does not have :my/attribute • entity does not have :my/attribute and we're using nil to signal some meta information In most cases I can think I can think of, you should probably either 1) add extra meta-data to the entity as its own attribute or 2) use a more meaningful value than nil to represent this alternate state (but usually 1). Can you describe a use case where you would want to store nil for an attribute?

Oliver George01:05:23

In terms of a data model it's questionable. If datascript silently dropped nil attrs from transactions I'd probably not have bought it up. Clojure idioms don't make a hard distinction between missing attr and nil attr so there is an impedance mismatch when datascript doesn't get the joke (nil pun pun intended). I do have nils in map values because they tend to slosh through my code. Keeping nils out of maps is somewhat inconvenient. (e.g. in the code I was working on yesterday keeping nils out requires changing (assoc m :my/attr a-value) to (cond-> m a-value assoc :a-value a-value) and being clear when that a-value might not be set which means always doing it). An alternative would be wrapping the tx-data calls to strip any nil attrs.

Niki11:05:35

When I worked with DataScript a lot, I used to have map-some, assoc-some and update-some methods that would create/update maps only if value is not nil. A bit inconvenient, but tolerable

imre09:05:57

> Clojure idioms don't make a hard distinction between missing attr and nil attr so there is an impedance mismatch when datascript doesn't get the joke There are Clojure idioms that do make that hard distinction and IMO those contribute to the mismatch. Some examples are keyword destructuring:

(let [{:keys [foo bar] :or {foo 1 bar 2}} {:foo nil}] [foo bar])
=> [nil 2]
and merge:
(merge {:foo 1 :bar 2} {:foo nil})
=> {:foo nil, :bar 2}
In the above examples {:foo nil} and {} would give results that are different even when later code doesn't make a distinction between a missing key and nil.

👍 1
Oliver George10:05:32

Fair points. I guess that takes some wind out of the "why not silently drop them" idea.