ANN: ClojureScript 0.0-2644, enhanced REPLs

391 views
Skip to first unread message

David Nolen

unread,
Jan 2, 2015, 6:19:02 PM1/2/15
to clojure, clojur...@googlegroups.com
ClojureScript, the Clojure compiler that emits JavaScript source code.

README and source code: https://github.com/clojure/clojurescript

New release version: 0.0-2644

Leiningen dependency information:

[org.clojure/clojurescript "0.0-2644"]

This release is one of the most significant in a very long while - it includes
enhanced REPLs that are far closer to the experience provided by Clojure
itself.

All REPLs when supplied with an `:output-dir` & `:cache-analysis true` can
now boot rapidly - a second or less on newer hardware.

All REPLs now support `in-ns`, `doc`, and `require`.

There is a brand new Node.js based REPL that doesn't suffer from the performance
issues present in Rhino. As to why we didn't go with Nashorn - Nashorn loads
JavaScript 10X slower than Rhino or Node.js.

The Node.js REPL ships with source mapping support and correctly handles
Node.js requires so that you can hot update namespaces as expected.

There were a large number of changes to enhance the REPL experience so
there's likely edge cases we've missed - feedback, bug fixes, and further
enhancement are incredibly welcome.

For basic instructions on the running the REPLs from a checkout:

https://github.com/clojure/clojurescript/wiki/Quick-Start#local-clojurescript-repl

## 0.0-2644

### Enhancements
* Add Node.js REPL
* REPLs can now reuse build/analysis caching
* in-ns, require, doc support in REPLs

### Changes
* add :verbose flag to compiler to output compiler activity
* add *load-macros* to cljs.analyzer to optionally disable macro loading
* errors during ns parsing always through
* `cljs.util/compiled-by-version` needs to always return String
* pin Closure Compiler in bootstrap script
* refactor cljs.build.api namespace

### Fixes
* CLJS-953: require REPL special fn can only take one argument
* CLJS-952: Bad type hinting on bit-test
* CLJS-947: REPL require of goog namespaces does not work
* CLJS-951: goog.require emitted multiple times under Node.js REPL
* CLJS-946: goog.require in REPLs will not reload recompiled libs
* CLJS-950: Revert adding compiled-by string to CLJS deps file
* CLJS-929: Minor fixes to test script
* CLJS-946: goog.require in REPLs will not reload recompiled libs
* add cljs.test/are macro
* CLJS-931 : cljs.compiler/requires-compilation? ignores changes to
build options
* CLJS-943: REPL require special fn is brittle
* CLJS-941: Warn when a symbol is defined multiple times in a file
* CLJS-942: Randomized port for Node.js REPL if port not specified
* CLJS-675: QuickStart example not working properly
* CLJS-935: script/noderepljs leaves node running after exit
* CLJS-918: preserve :arglists metadata in analysis cache
* CLJS-907: False positives from arithmetic checks
* CLJS-919 compare-and-set! relies on Atom record structure instead of protocols
* CLJS-920 add-watch/remove-watch should return reference, as in Clojure
* CLJS-921: cljs.repl/doc output includes namespace twice

Mimmo Cosenza

unread,
Jan 2, 2015, 6:35:35 PM1/2/15
to clojur...@googlegroups.com, clo...@googlegroups.com
may I borrow some energy from you?
you’re awesome
thanks, thanks. thanks so much!

mimmo
> --
> Note that posts from new members are moderated - please be patient with your first post.
> ---
> You received this message because you are subscribed to the Google Groups "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
> To post to this group, send email to clojur...@googlegroups.com.
> Visit this group at http://groups.google.com/group/clojurescript.

David Nolen

unread,
Jan 2, 2015, 9:01:59 PM1/2/15
to clojure, clojur...@googlegroups.com
Forgot to add for maintainers of existing custom REPLs the following
is essential reading:

https://github.com/clojure/clojurescript/wiki/Custom-REPLs

Most of the changes have been made towards *decreasing* the amount of
custom logic REPLs need to implement. -setup really becomes a
bootstrapping process after which the shared infrastructure takes
over.

Max Gonzih

unread,
Jan 3, 2015, 9:02:15 AM1/3/15
to clojur...@googlegroups.com, clo...@googlegroups.com
Any idea why Nashorn is slower? Is it related to type checks?

David Nolen

unread,
Jan 3, 2015, 10:33:29 AM1/3/15
to clojur...@googlegroups.com
It just has known performance issues loading code - there's no interpreter & warmup time is really bad.


On Saturday, January 3, 2015, Max Gonzih <gon...@gmail.com> wrote:
Any idea why Nashorn is slower? Is it related to type checks?

David Nolen

unread,
Jan 3, 2015, 2:40:10 PM1/3/15
to clojure, clojur...@googlegroups.com
Just pushed out 0.0-2655, the main change is that REPLs now respect
Clojure semantics wrt. to `require`. Loaded libs are not reloaded
unless `:reload` or `:reload-all` is supplied to the `ns` or `require`
form same as Clojure.

David

### Changes
* add defonced cljs.core/*loaded-libs* dynamic var
* cljs.core/*print-fn* is now defonced
* throw on (var foo) when foo is not defined
* cljs.analyzer.api/resolve matches cljs.core/resolve if
var doesn't exist return nil

### Fixes
* require needs to respect Clojure semantics, do not
reload unless requested
* add ns/require support for :reload & :reload-all

On Fri, Jan 2, 2015 at 6:18 PM, David Nolen <dnolen...@gmail.com> wrote:

David Nolen

unread,
Jan 3, 2015, 5:30:43 PM1/3/15
to clojure, clojur...@googlegroups.com
0.0-2257 released, only change is the addition of `require-macros`
REPL special function for importing macros from libraries like
core.async.

On Fri, Jan 2, 2015 at 6:18 PM, David Nolen <dnolen...@gmail.com> wrote:

David Nolen

unread,
Jan 3, 2015, 5:31:06 PM1/3/15
to clojure, clojur...@googlegroups.com
Oops that should be 0.0-2657 of course.

David

gvim

unread,
Jan 3, 2015, 10:28:44 PM1/3/15
to clojur...@googlegroups.com
Great effort, David. One little improvement - on my Mac OS X Yosemite
machine the 'ClojureScript:cljs.user>' repl does not appear to support
readline unlike the leiningen Clojure repl.

gvim

David Nolen

unread,
Jan 3, 2015, 10:33:01 PM1/3/15
to clojur...@googlegroups.com
Works with rlwrap for me and others. Can you be more specific about what you have tried?

gvim

unread,
Jan 3, 2015, 10:43:16 PM1/3/15
to clojur...@googlegroups.com
Update: readline wasn't working when I downloaded from the git
repository but it works when downloading via `lein new mies <project name>`

gvim

On 02/01/2015 23:18, David Nolen wrote:

gvim

unread,
Jan 3, 2015, 10:59:49 PM1/3/15
to clojur...@googlegroups.com
I'm using MacPorts but rlwrap and node are on my PATH. I followed the
README.md, ie.

cd samples/repl
../../script/repl


(require '[cljs.closure :as cljsc])
(def opts {:output-to "main.js" :output-dir "out"})
(cljsc/build "src" opts)


(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)


.... then:

ClojureScript:cljs.user> (.write js/document "Hi")

... which produced 'Hi' in the browser but produced only a carriage
return in the terminal instead of returning the repl prompt. Attempts to
use up arrow produced only ^[[A^[[A^[[A character sequences.

I should add it's possible I may be overlooking something quite obvious :(

gvim



On 04/01/2015 03:32, David Nolen wrote:
> Works with rlwrap for me and others. Can you be more specific about what
> you have tried?
>
> On Saturday, January 3, 2015, gvim <gvi...@gmail.com

David Nolen

unread,
Jan 3, 2015, 11:46:51 PM1/3/15
to clojur...@googlegroups.com
That's the just standard Browser REPL, trying to use rlwrap or
readline w/ that approach probably isn't going to work. You'll want to
look at how mies does it and copy the approach -
http://swannodette.github.io/2015/01/02/the-essence-of-clojurescript-redux/.

David

Ivan L

unread,
Jan 4, 2015, 3:15:32 AM1/4/15
to clojur...@googlegroups.com
Would you expect the latest release to break cljsbuilds repl?

I get this in a project I just upgraded.

C:\Users\me\workspace\cljd3>lein trampoline cljsbuild repl-rhino
Running Rhino-based ClojureScript REPL.
To quit, type: :cljs/quit
Error: Namespace "goog.debug.Error" already declared. (goog/base.js#248)
Error: Namespace "goog.asserts" already declared. (goog/base.js#248)
Error: Namespace "goog.string" already declared. (goog/base.js#248)
java.lang.NullPointerException
at sun.misc.MetaIndex.mayContain(Unknown Source)
at sun.misc.URLClassPath$JarLoader.getResource(Unknown Source)
at sun.misc.URLClassPath.getResource(Unknown Source)
at sun.misc.URLClassPath.getResource(Unknown Source)
at java.lang.ClassLoader.getBootstrapResource(Unknown Source)
at java.lang.ClassLoader.getResource(Unknown Source)
at java.lang.ClassLoader.getResource(Unknown Source)
at clojure.java.io$resource.invoke(io.clj:441)
at clojure.java.io$resource.invoke(io.clj:440)
at cljs.closure$source_for_namespace.invoke(closure.clj:487)
at cljs.repl$load_namespace.invoke(repl.clj:57)
at cljs.repl$load_dependencies.invoke(repl.clj:77)
at cljs.repl$evaluate_form.invoke(repl.clj:130)
at cljs.repl$repl_STAR_.invoke(repl.clj:286)
at cljs.repl$repl.doInvoke(repl.clj:329)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at cljsbuild.repl.rhino$run_repl_rhino.invoke(rhino.clj:8)
at user$eval3600.invoke(form-init4971663832168098969.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6703)
at clojure.lang.Compiler.eval(Compiler.java:6693)
at clojure.lang.Compiler.load(Compiler.java:7130)
at clojure.lang.Compiler.loadFile(Compiler.java:7086)
at clojure.main$load_script.invoke(main.clj:274)
at clojure.main$init_opt.invoke(main.clj:279)
at clojure.main$initialize.invoke(main.clj:307)
at clojure.main$null_opt.invoke(main.clj:342)
at clojure.main$main.doInvoke(main.clj:420)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
java.lang.NullPointerException
ClojureScript:cljs.user>

Angel Java Lopez

unread,
Jan 4, 2015, 4:25:46 AM1/4/15
to clojur...@googlegroups.com
Same here

C:\Git\ClojureScriptSamples\mycljsprj>lein trampoline cljsbuild repl-rhino
Running Rhino-based ClojureScript REPL.
To quit, type: :cljs/quit
Error: Namespace "goog.debug.Error" already declared. (goog/base.js#248)
Error: Namespace "goog.asserts" already declared. (goog/base.js#248)
Error: Namespace "goog.string" already declared. (goog/base.js#248)
java.lang.NullPointerException
        at sun.misc.MetaIndex.mayContain(Unknown Source)
        at sun.misc.URLClassPath$JarLoader.getResource(Unknown Source)
        at sun.misc.URLClassPath.getResource(Unknown Source)
        at sun.misc.URLClassPath.getResource(Unknown Source)
        at java.lang.ClassLoader.getBootstrapResource(Unknown Source)
        at java.lang.ClassLoader.getResource(Unknown Source)
        at java.lang.ClassLoader.getResource(Unknown Source)
        at clojure.java.io$resource.invoke(io.clj:441)
        at clojure.java.io$resource.invoke(io.clj:440)
        at cljs.closure$source_for_namespace.invoke(closure.clj:487)
        at cljs.repl$load_namespace.invoke(repl.clj:57)
        at cljs.repl$load_dependencies.invoke(repl.clj:77)
        at cljs.repl$evaluate_form.invoke(repl.clj:130)
        at cljs.repl$repl_STAR_.invoke(repl.clj:286)
        at cljs.repl$repl.doInvoke(repl.clj:329)
        at clojure.lang.RestFn.invoke(RestFn.java:410)
        at cljsbuild.repl.rhino$run_repl_rhino.invoke(rhino.clj:8)
        at user$eval2903.invoke(form-init4629269018090110698.clj:1)
        at clojure.lang.Compiler.eval(Compiler.java:6703)
        at clojure.lang.Compiler.eval(Compiler.java:6693)
        at clojure.lang.Compiler.load(Compiler.java:7130)
        at clojure.lang.Compiler.loadFile(Compiler.java:7086)
        at clojure.main$load_script.invoke(main.clj:274)
        at clojure.main$init_opt.invoke(main.clj:279)
        at clojure.main$initialize.invoke(main.clj:307)
        at clojure.main$null_opt.invoke(main.clj:342)
        at clojure.main$main.doInvoke(main.clj:420)
        at clojure.lang.RestFn.invoke(RestFn.java:421)
        at clojure.lang.Var.invoke(Var.java:383)
        at clojure.lang.AFn.applyToHelper(AFn.java:156)
        at clojure.lang.Var.applyTo(Var.java:700)
        at clojure.main.main(main.java:37)
java.lang.NullPointerException
ClojureScript:cljs.user>

The REPL is working:

ClojureScript:cljs.user> 1
1
ClojureScript:cljs.user> (+ 1 2)
3
ClojureScript:cljs.user> (first '(a b))
a
ClojureScript:cljs.user> ((fn [x] (+ x 1)) 5)
6
ClojureScript:cljs.user> (last '(1 2 3))
3
ClojureScript:cljs.user> (butlast '(1 2 3))
(1 2)
ClojureScript:cljs.user> (vector 1 2 3)
[1 2 3]
ClojureScript:cljs.user>

My project

Angel "Java" Lopez
@ajlopez


David Nolen

unread,
Jan 4, 2015, 11:24:16 AM1/4/15
to clojur...@googlegroups.com
Yes all REPLs that do not ship with ClojureScript will need updating. In the meantime you can just use them directly instead of going through cljsbuild. As I said above see the new mies template or the REPL runners that come with ClojureScript to see how.

David Nolen

unread,
Jan 4, 2015, 1:03:18 PM1/4/15
to clojure, clojur...@googlegroups.com
Release 0.0-2665, mostly to fix various issues introduced with the
REPL enhancements

### Changes
* REPL -setup now must take opts
* CLJS-916: Optimize use of js-arguments in array and variadic
functions
* special case `'cljs.core/unquote`
* CLJS-945: Compile core with :static-fns true by default
* CLJS-958: Node.js REPL: Upon error, last successfully item printed

On Fri, Jan 2, 2015 at 6:18 PM, David Nolen <dnolen...@gmail.com> wrote:

David Nolen

unread,
Jan 4, 2015, 1:14:47 PM1/4/15
to clojur...@googlegroups.com
I've written up instructions on how to run ClojureScript REPLs without
using cljsbuild and other 3rd party tools -

https://github.com/clojure/clojurescript/wiki/Running-REPLs
Reply all
Reply to author
Forward
0 new messages