datomic

Ask questions on the official Q&A site at https://ask.datomic.com!
joshkh 2020-11-19T13:51:10.459100Z

nil is meant to be allowed in heterogenous tuples, right? for example, let's say i have a tuple like this: [:db.type/ref :db.type/ref] and nil in the second value {:person/parents [123456 nil]} i get an exception when i untuple and bind on the nil value

(d/q '{:find  [?person ?parent-a-name]
       :in    [$]
       :where [
               [?person :person/parents ?parents-tuple]
               [(untuple ?parents-tuple) [?parent-a ?parent-b]]
               [?parent-a :person/name ?parent-a-name]
               [?parent-b :person/name] ;<-- throws exception
               ]}
     db)
Execution error (NullPointerException) at datomic.core.db/asserting-datum (db.clj:-1).
null
clojure.lang.ExceptionInfo: processing clause: [?parent-b :parent/name], message:  #:cognitect.anomalies{:category :cognitect.anomalies/incorrect, :message "processing clause: [?parent-b :parent/name], message: "}

joshkh 2020-11-20T09:43:48.464900Z

i don't think this is a composite tuple though. this is a heterogenous tuple.

favila 2020-11-20T13:04:14.465500Z

Heterogeneous tuples cannot contain refs

joshkh 2020-11-21T15:17:27.467900Z

hmm, i don't doubt what you're saying.. maybe i'm just confused here. i thought this is a heterogeneous tuple (from the schema in the forum post above):

{:db/ident       :person/parents
 :db/valueType   :db.type/tuple
 :db/tupleTypes  [:db.type/ref :db.type/ref]
 :db/cardinality :db.cardinality/one}
which allows refs, and works with transactions and pulls. are you saying that hetero tuples shouldn't contain refs, rather than cannot contain refs?

favila 2020-11-23T13:34:04.481Z

they shouldn’t, and I thought they could not

favila 2020-11-23T13:34:12.481200Z

if you read the docs, they make no mention of this

favila 2020-11-23T13:34:44.481400Z

also conceptually, it’s bad: ref values are supposed to be managed by datomic--this is no different than putting a long into a tuple

favila 2020-11-23T13:35:27.481600Z

with composite tuples, it knows what assertion it’s denormalized from; here, there is no support. and you can’t use lookup refs or keywords or tempids to reference these

favila 2020-11-23T13:36:33.481800Z

docs: https://docs.datomic.com/on-prem/schema.html#tuples

favila 2020-11-23T13:37:33.482100Z

I’m wrong though, :db.type/ref is lised as a scalar type

favila 2020-11-23T13:38:04.482300Z

I am pretty sure it wasn’t the last time I read this--maybe a change? Anyway, it still seems like a bad idea

favila 2020-11-23T13:38:28.482500Z

but if you really need to do it, queries needs to be defensive against nils

favila 2020-11-23T13:41:05.482900Z

[(!= ?x nil)] immediately might work, [(some? ?x)] should definitely work.

joshkh 2020-11-26T16:46:36.011700Z

hey favila, both of your solutions worked. thanks. in my case i'm storing some rankings in tuples...

{:race/finishers [[0 sally-ref coach-1-ref]
                  [1 bob-ref nil]
                  [2 jane-ref coach-2-ref]]}
of course the alternative (and more verbose) solution is to have separate ranking entities that store all of the context (the race, the people involved, and a rank), but as an experiment i thought tuples might be an interesting solution. in my example i don't see why storing references in tuples seems like a bad idea.

kschltz 2020-11-19T19:40:27.459200Z

@joshkh I'm afraid you can't have nil there

kschltz 2020-11-19T19:41:10.459400Z

If I'm not mistaken the value just would not be there

kschltz 2020-11-19T19:41:24.459600Z

{:parents [123456]}

joshkh 2020-11-19T19:56:17.460Z

that makes sense to me. do you know if that is the official stance? i am allowed to both transact and pull nil values. as for binding i would have expected the query to not unify instead of throw an exception

kschltz 2020-11-19T20:13:40.460200Z

I believe you get that exception because theres actually a value (nil), which makes the whole hting unify but it wont comply to your clause :person/name

kschltz 2020-11-19T20:14:34.460400Z

That would be my guess

joshkh 2020-11-19T20:54:39.460600Z

fair enough 🙂

joshkh 2020-11-19T20:56:05.460800Z

just a funny observation: when retracting an entity referenced in a tuple, the tuple retrains the entity db/id even after the target has been retracted. that feels equally strange to me but for other reasons.

kschltz 2020-11-19T20:58:12.461Z

Not sure why, but I think if you look at it like independent datoms, kinda makes sense. Its not like a component, where you retract the mother entity and the child follows along. But you have a fair point

joshkh 2020-11-19T21:09:17.461300Z

also from Jaret on the forums (at least regarding homogenous tuples) > Additionally you may be interested in knowing that, `nil` is a legal value for any slot in a tuple. This facilitates using tuples in range searches, where `nil` sorts lowest. https://forum.datomic.com/t/tuple-with-single-item-fails-transaction/1690

😮 1
joshkh 2020-11-19T21:10:00.461600Z

maybe i'll make an ol' posteroo on the forums

kschltz 2020-11-19T21:11:06.461900Z

I hope Jaret get a raise soon enough, he's always the one to respond my tickets xD

joshkh 2020-11-19T21:13:02.462100Z

Jaret and Marshall both do a great job of putting up with my bs 😎

kschltz 2020-11-19T21:13:41.462300Z

couldn't say it better

joshkh 2020-11-19T21:36:26.462500Z

(in case someone from Cognitect reads the thread, i've posted the question here: https://forum.datomic.com/t/nil-value-in-heterogeneous-tuple-throws-a-nullpointerexception/1693)

😄 1
favila 2020-11-19T22:32:39.462900Z

I think this is just a mismatch between datalog unification and how tuples are handled. Since this is a composite attribute, consider reading the source attribute value instead of the composite

favila 2020-11-19T22:34:05.463100Z

(I’ve often wished for composite attributes to have a “not nillable” option, so that they are not asserted unless all values are present)