Def Vars in ClojureScript REPLs
Fairly recently, ClojureScript gained static vars. A good intro, right from the horse's mouth is: What's in a Var?
But there remains a significant difference between Clojure and ClojureScript when it comes to def
and derived forms: In Clojure, def
returns the var being defined, while in ClojureScript it returns the value of the var.
Here is an example from the Clojure REPL:
user=> (def a 3)
#'user/a
And here is the same in the ClojureScript REPL:
cljs.user=> (def a 3)
3
No biggie. But, consider function definitions.
Clojure:
user=> (defn square [x] (* x x))
#'user/square
ClojureScript:
cljs.user=> (defn square [x] (* x x))
#<function cljs$user$square(x){
return (x * x);
}>
Yeah. This is not so bad, and seeing the emitted JavaScript can arguably be useful at times. But for larger function definitions, this can get to be a bit distracting and annoying, IMHO.
But now that we have vars, we can revise this behavior, at least for def
s evaluated at the REPL, leaving compiled code to the existing behavior.
Here is some sample output for work being done towards CLJS-934:
cljs.user=> (def a 3)
#'cljs.user/a
cljs.user=> (defn square [x] (* x x))
#'cljs.user/square
Yay! Civilized even!
Another nice consequence is that you can define infinite lazy sequences in the REPL:
cljs.user=> (def naturals (map inc (range)))
#'cljs.user/naturals
cljs.user=> (take 11 naturals)
(1 2 3 4 5 6 7 8 9 10 11)
You can also (but only in the REPL), use the return value of a def
form as the var it really is:
cljs.user=> @(def a 3)
3
cljs.user=> ((defn square [x] (* x x)) 3)
9
Note this last example exercises the evaluation rule that, for function position, a var evaluates to its value (the square
function itself), which is then applied.
If you want the old behavior—perhaps to see the emitted JavaScript—it is just a @
away:
cljs.user=> @(defn square [x] (* x x))
#<function cljs$user$square(x) {
return (x * x);
}>