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:
- by calling the tempid API method
- with a data literal, e.g.
#db/id[:db.part/user]
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.
1 Comments
This is very useful information. I believe the reason it is "a common mistake" is that the documentation at http://docs.datomic.com/database-functions.html has no examples of using d/function.