If you call clojure.tools.namespace.repl/refresh
before requiring any
namespaces referenced in data_readers.clj
, then *data-readers*
gets messed
up somehow. The readers you define in data_readers.clj
won't work even if you
require their namespaces. For example:
$ find -type f
./src/foo/core.clj
./src/data_readers.clj
./src/user.clj
./deps.edn
$ for f in $(find -type f); do echo $f:; cat $f; echo; done
./src/foo/core.clj:
(ns foo.core)
(defn foo-reader [x]
(Long/parseLong x))
./src/data_readers.clj:
{foo/bar foo.core/foo-reader}
./src/user.clj:
(ns user
(:require [clojure.tools.namespace.repl :refer [refresh]]))
(defn good []
(require 'foo.core)
(read-string "#foo/bar \"123\"") ; works
(refresh)
(read-string "#foo/bar \"123\"")) ; still works
(defn bad []
(refresh)
(require 'foo.core)
(read-string "#foo/bar \"123\"")) ; doesn't work
./deps.edn:
{:deps {org.clojure/tools.namespace {:mvn/version "0.2.11"}}}
$ clj -e "(good)"
:reloading (user foo.core)
123
$ clj -e "(bad)"
:reloading (user foo.core)
Exception in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'foo.core/foo-reader
at clojure.lang.Var$Unbound.throwArity(Var.java:45)
at clojure.lang.AFn.invoke(AFn.java:32)
at clojure.lang.Var.invoke(Var.java:384)
at clojure.lang.LispReader$CtorReader.readTagged(LispReader.java:1448)
at clojure.lang.LispReader$CtorReader.invoke(LispReader.java:1427)
at clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:846)
at clojure.lang.LispReader.read(LispReader.java:285)
at clojure.lang.LispReader.read(LispReader.java:216)
at clojure.lang.LispReader.read(LispReader.java:205)
at clojure.lang.RT.readString(RT.java:1874)
at clojure.lang.RT.readString(RT.java:1869)
at clojure.core$read_string.invokeStatic(core.clj:3815)
at clojure.core$read_string.invoke(core.clj:3805)
at user$bad.invokeStatic(user.clj:13)
at user$bad.invoke(user.clj:10)
at user$eval535.invokeStatic(NO_SOURCE_FILE:1)
at user$eval535.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:7176)
at clojure.lang.Compiler.eval(Compiler.java:7131)
at clojure.core$eval.invokeStatic(core.clj:3214)
at clojure.main$eval_opt.invokeStatic(main.clj:465)
at clojure.main$eval_opt.invoke(main.clj:459)
at clojure.main$initialize.invokeStatic(main.clj:485)
at clojure.main$null_opt.invokeStatic(main.clj:519)
at clojure.main$null_opt.invoke(main.clj:516)
at clojure.main$main.invokeStatic(main.clj:598)
at clojure.main$main.doInvoke(main.clj:561)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:37)
I'm not sure why this happens, but you can fix it by requiring any namespaces
in data_readers.clj
from your user.clj
file (or whatever your repl
entrypoint is). As long as you require them before the first call to refresh
,
they'll work.