Stop requiring precompilation for REPL-ing
cemerick opened this issue · comments
The REPL middleware works well, but it doesn't help when you load a file or evaluate an expression that requires some other namespace that:
- Is defined in a .cljx file, and
- Has not already been precompiled into Clojure/ClojureScript already.
The REPL middleware needs to intercept load
calls so that e.g. (require 'foo)
will look for a foo.cljx
resource on the classpath, cljx
it to Clojure/ClojureScript based on the prevailing rules, and then invoke the regular file-loading mechanism for the type of REPL session in progress. Of course, if a .cljx
file isn't available, the normal loading mechanism should apply.
Done pervasively/properly, this should make cljx precompilation entirely unnecessary except when cutting a jar/war/other distributable.
Should note that the workaround right now, if you're in a REPL and there's an ns dependency that hasn't been precompiled that you need, you can just open it in a buffer/window/whatever, and load it. This can mean manually walking down the require
dep graph, which sucks…thus the appeal of making this "fix" happen.
Just for the sake of completion, when you say "open it .... and load it." do you mean the cljx file or the cljs/clj file?
Assuming you're using nREPL and the cljx middleware, I mean the cljx file. If you're not doing both, then the only way to load the code produced from cljx files is to run lein cljx
, and then (require ...)
the generated files from disk.
Halfway there. When you have the cljx nREPL middleware installed, it monkey-patches clojure.core/load
to find, transform, and load .cljx
files matching namespaces named in e.g. require
and use
forms in preference to any .clj
files. This means you don't have to run lein cljx once
before doing your Clojure REPL-ing, even if you're going to be loading .cljx
-implemented namespaces (transitively or not).
Next step: same support for ClojureScript.
(BTW, "monkey-patching clojure.core/load
" is a lot less scary than it sounds. load
hasn't materially changed in > 4 years, so cljx swapping in its own implementation [which is 90% the same as clojure.core
's] is very low-risk. That said, please report any breakage you find, and I'll get on it! :-) )
(Notes for my benefit)
ClojureScript compiler changes TODO (all in closure):
- factor out
ns->cp
so it can be patched too (to return aCompilable
- generalize
cljs-deps
so it passesCompilable
s on untouched
OK, this now works for ClojureScript, too, and it ended up not requiring any compiler changes there. This is available in [com.keminglabs/cljx "0.3.3-SNAPSHOT"]
.
Clojurescript cljx REPLing doesn't work here:
> lein repl
nREPL server started on port 50204 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
To start Austin, type: (cemerick.piggieback/cljs-repl :repl-env (cemerick.austin/exec-env))
Type (refresh) to reload all namespaces.
user=> (cemerick.piggieback/cljs-repl :repl-env (cemerick.austin/exec-env))
Browser-REPL ready @ http://localhost:50323/9580/repl/start
Type `:cljs/quit` to stop the ClojureScript REPL
nil
cljs.user=> (require 'namban.boeki)
"Error evaluating:" (require (quote namban.boeki)) :as ".require.call(null,new cljs.core.Symbol(null,\"namban.boeki\",\"namban.boeki\",-2013049770,null));\n"
#<SyntaxError: Parse error>
No stacktrace available.
nil
The project.clj.
Clojure cljx REPLing works though.
lein deps :tree suggested me to include [com.keminglabs/cljx "0.3.3-20140218.213435-1" :exclusions [org.clojure/clojure]]
in project.clj
but it's still not working and nothing changed in lein deps :tree
.
Perhaps you used a different REPL environment to test that feature or something?
There is no require
function in ClojureScript. You need to use either an ns
form, or e.g. (load-namespace 'namban.boeki)
.
Yes, I also noticed that embarrassing fact some minutes ago :)