Grant
Grant

Reputation: 221

core.typed + datomic = No reader function for tag id

I'm just getting started with clojure and core.typed, and keep running into the following error when I evaluate (check-ns 'stocks.db) with the following code:

(ns stocks.db
  (:gen-class)
  (:require [clojure.core.typed :refer [ann HMap]]))

(use '[datomic.api :only [q db] :as d])

(ann break-me [String -> (HMap)])
(defn break-me
  "Do I break cored.typed?"
  []
  {:db/id #db/id[:db.part/db]})

ExceptionInfo No reader function for tag id clojure.core/ex-info (core.clj:4327)

(break-me) evaluates to {:db/id #db/id[:db.part/db -1000000]} as you'd expect.

Similarly to this unanswered question, the offending term is definitely #db/id.

Thanks for any help.

Upvotes: 1

Views: 1189

Answers (1)

user266647
user266647

Reputation:

I'm new to Clojure and Datomic but, I think you need to generate your temporary id with the tempid function that's part of the Datomic API (see http://docs.datomic.com/clojure/index.html#datomic.api/tempid).

So it'd look like this:

(ns stocks.db
  (:gen-class)
  (:require [clojure.core.typed :refer [ann HMap]]))

(use '[datomic.api :only [q db] :as d])

(ann break-me [String -> (HMap)])
(defn break-me
  "Do I break cored.typed?"
  []
  {:db/id (tempid :db.part/db)})

I'm having similar issues with clojure.edn/read-string, I haven't quite figured it out. Hope that works for you.

UPDATE: In this code: https://github.com/Datomic/codeq/blob/master/src/datomic/codeq/core.clj the Datomic folks seem to be doing just what you are. So while in your case I think using tempid will work, I think there's a deeper issue, and it seems like it has to do with the literal #db/id.

UPDATE: Here: https://github.com/Datomic/day-of-datomic/blob/master/samples/literals_vs_code.clj using tempid rather than literals is recommended.

UPDATE: I've found a solution that also resolves my issue. I was trying to read in my schema from a file: schema.edn using clojure.edn/read-string after reading the contents as a string using clojure.core/slurp and got similar error complaining about the #db/id literal.

I implemented the read-all and transact-all functions found here: https://github.com/Datomic/day-of-datomic/blob/053b3bd983d165b8fa7c0c039712fb1cb75eddf3/src/datomic/samples/io.clj and it works fine. It seems like there are some sneaky issues with using the reader to parse #db/id literals, still haven't figured out exactly why.

UPDATE: This is using a Clojure feature called "tagged literals" which allows you to define a map of "data readers" in a file named data_readers.clj at the root of your classpath that should contain a map of tag names and vars that will parse the arguments to the tag.

So with this data_readers.clj file:

{minutes my.project/to-minutes
 seconds my.project/to-seconds}

You can do this:

#minutes 3
#seconds 4

You can read about tagged literals at the bottom of this page: http://clojure.org/reader.

However, I still have not figured out the reason for the issue with the #db/id tagged literal. I've posted a question on the Clojure group forum here: https://groups.google.com/forum/#!topic/datomic/Fi7iXps2npw. Update: Ben Kamphaus provides a nice explanation there.

Upvotes: 4

Related Questions