Fork me on GitHub
#datomic
<
2022-09-14
>
seepel07:09:54

After using Datomic for the last couple of months I had an idea to implement https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule in the database. I'm wondering how bad an idea is modeling https://en.wikipedia.org/wiki/Hash_consing lists with a schema like this?

[{:db/ident :pair/car
  :db/valueType :db.type/ref
  :db/cardinality :db.cardinality/one}
 {:db/ident :pair/cdr
  :db/valueType :db.type/ref
  :db/cardinality :db.cardinality/one}
 {:db/ident :pair/car+cdr
  :db/valueType :db.type/tuple
  :db/tupleAttrs [:pair/car :pair/cdr]
  :db/cardinality :db.cardinality/one
  :db/unique :db.unique/identity}]

hanDerPeder09:09:50

in the docs for datomic.api/entity it says an entity implements clojure.lang.Associative, but when I do (assoc my-entity :foo 1) I get an exception

1. Unhandled java.lang.AbstractMethodError
   Receiver class datomic.query.EntityMap does not define or inherit
   an implementation of the resolved method 'abstract
   clojure.lang.Associative assoc(java.lang.Object, java.lang.Object)'
   of interface clojure.lang.Associative.
also
(instance? clojure.lang.Associative my-entity) ;; => true

hanDerPeder09:09:15

looking at (datafy datomic.query.EntityMap) I see clojure.lang.Associative under :bases but no assoc under members. Am I not understanding what “implements” means?

magnars10:09:52

If you are looking to assoc on Datomic entities, here's some code that lets your wrap a Datomic entity - keeping its semantics, while also accepting assoc. I'm not sure it's a good idea tho. https://gist.github.com/magnars/f2fb046904e7c1ea57dca7058266da1d

hanDerPeder10:09:57

neat! still curious why it says on the tin that entity implements clojure.lang.Associative while it seems it really does not.

magnars10:09:08

In case you're wondering about the clojurescript part of the code, that's for using datascript in the browser. It's been in use for several years, so it's pretty battle tested code.

favila11:09:50

It implements the containsKey and entryAt=>MapEntry methods, but not assoc

favila11:09:45

You don't have to implement every method to “implement” (in Java instanceof sense) an interface

hanDerPeder11:09:57

TIL, thanks :thumbsup:

JohnJ16:09:27

doesn't Java force you though? (excluding default methods)

favila16:09:51

java the language does, not the JVM/runtime

favila16:09:40

E.g. you can reify/gen-class/deftype/defrecord in clojure and only partially implement an interface, and clojure will happily generate the class bytecode and the jvm will accept it and just runtime error if you try to call a missing method

favila16:09:58

the java compiler OTOH will prevent you

👍 1
JohnJ17:09:45

Though most of datomic was implemented in Java for performance reasons

favila17:09:04

eh, I don’t think that’s true

favila17:09:29

if you look in the jar, it sure looks like mostly AOTed clojure code

favila17:09:49

judging from class names etc

favila17:09:03

some key parts are java though, like fressian

favila17:09:11

Also there are an awful lot of datomic namespaces

favila17:09:37

if you just introspect at runtime after requiring datomic.api

JohnJ17:09:29

ah neat, would be interesting to know how many lines of clojure make up datomic

pppaul21:09:49

you can walk your entity and run (into {}) at each level where appropriate, or just run it at top level without the walk, then you get your normal map instead of a datomic ent (maybe sometimes you want this, but you also get this with a pull, which is probably better than walking an entity)

hanDerPeder19:09:19

is this transaction a no-op or will the history include this?

[[:db/retract 123 :foo/bar 1]
   [:db/add     123 :foo/bar 1]]
I could check myself, but haven’t learned how to yet

magnars19:09:37

It will fail with

Two datoms in the same transaction conflict

hanDerPeder19:09:15

that’s disappointing. thanks though 🙂

ghadi20:09:41

Why is that disappointing? It’s a non sensical transaction

hanDerPeder21:09:02

Disappointing in the sense that I need to apply myself.