When to Use Data Literals

Datomic data structures have the same syntax as JVM languages, where feasible. But several data structures do not have a canonical literal representation in the JVM world, e.g. tempids and database functions.  In such cases, Datomic offers both edn data literals and a constructor method. For example, you can create tempids either:

The rule for choosing between data and code representations is easy: code should use code, and data should use data. In other words, your programs should call the APIs, and data files should use data literals.

A common mistake is to attempt to use database function literals in code. The example below attempts to create a database function from a program, but incorrectly uses a data literal representation

;; broken, uses db/fn literal in code
(transact conn [{:db/id #db/id [:db.part/user]
                 :db/ident :hello
                 :db/fn #db/fn {:lang "clojure"
                                :params []
                                :code '(println :hello)}}])


Executing the example above causes an error:

       Can't embed object in code

The corrected version below uses the d/function API call to create the database function, and the d/tempid API call to create the temporary entity id.

;; corrected: used d/function to construct function
(transact conn [{:db/id (d/tempid :db.part/user)
                 :db/ident :hello
                 :db/fn (d/function {:lang "clojure"
                                     :params []
                                     :code '(println :hello)})}])
(d/invoke (db conn) :hello)


The complete code to accompany this article is available as part of the Day of Datomic tutorial project.

Have more questions? Submit a request


Please sign in to leave a comment.
Powered by Zendesk