
ClojureScript 1.7: ClojureScript can compile itself - programnature
http://swannodette.github.io/2015/07/29/clojurescript-17/
======
krat0sprakhar
> We grabbed a string out of CodeMirror, read it via tools.reader into
> persistent data structures, passed it into the ClojureScript analyzer,
> constructed an immutable AST, passed that AST to the compiler, and generated
> JavaScript source with inline source maps and eval'ed the result. All of
> this happened inside of your web browser.

This is just fantastic! As David himself mentions - this might not be
extremely pragmatic but it sure as hell as cool. For me it means that I can
get back to writing my web-based Clojure book without being dependent on
Himera[0], which although great, is really hard to work with.

Awesome work by @swannodette and team!

[0] -
[https://himera.herokuapp.com/index.html](https://himera.herokuapp.com/index.html)

~~~
eggy
I don't pretend to know front end dev too much; I don't program for a living,
but it seems the 'bazaar' model of layering, patching and piling things up is
making that world unnecessarily complex. If I understand this thread
correctly, you lose Google's Closure optimizations(?), you go round about
AST->compiler->JavaScript and you can eval the result. Is the eval equivalent
to Scheme or Common Lisp? What are its limitations? I like what I see of
ClojureScript as a language syntax and some of the underlying concepts. I am
playing with PicoLisp and PilOS (PicoLisp running on a VM - not really a Lisp
Machine), and the simplicity and directness of it is refreshing. The layer of
abstractions are minimal. I guess that's the same reason I like the J
programming language. I am astounded by the amount of work and the
accomplishment here, but I have to wonder if we can't see the forest for the
trees any longer in computer science. Currently reading 'The Architecture of
Symbolic Computers', studying Shen, PicoLisp, Racket and the J programming
language. Perhaps my naivete of not having to work in this field, and the
luxury of being able to dabble across languages and systems has shifted my
perspective?

EDIT: How do you debug your work? What traces do you get back? Can you still
do REPL (like Emacs/Slime) this way?

~~~
weavejester
ClojureScript isn't particularly different to how most other languages work.
You have a parser (analyzer) that turns text into an AST, then a compiler that
turns the AST into the target code. In this case it's Javascript, but the same
principle applies if the target is assembly or bytecode.

ClojureScript is now self-hosting, which means that you can eval any valid
ClojureScript, so yes, eval in ClojureScript is now equivalent to the eval in
languages like Clojure, Racket or any other Lisp.

Usually when a language is bootstrapped, that becomes the new norm. For
instance, Go was originally mostly written in C, but since 1.5 Go has been
written in Go. However, the Java version of the ClojureScript compiler can
leverage Google's Closure Tools, which include a rather useful Javascript
optimizer. This means that we'll still want to use the Java version of
ClojureScript in most cases.

------
jeletonskelly
I swear David Nolan does not sleep.

~~~
swannodette
I do in fact enjoy sleeping immensely. As alluded to in the post while I tend
to do a lot of "driving" \- this release was the result of a broader effort by
the growing Clojure & ClojureScript communities.

~~~
DanielRibeiro
And we are very thankful for all your contributions David.

Thank you so much.

------
robohamburger
The most interesting case for me will be fast starting clojurescripts as the
author points out.

The one area I have not been happy with is clojure's startup times so
hopefully this fixes that going forward.

~~~
mfikes
It can be very fast to get things running. Here is an example using "desktop"
JavaScriptCore on OS X:
[https://twitter.com/mfikes/status/626884586392453120](https://twitter.com/mfikes/status/626884586392453120)

------
tbatchelli
This also means that we can use clojurescript as a scripting language. Will
make some systems automation much more fun!

~~~
michael_fine
I'm only vaguely familiar with clojure, but why would you want to use
clojurescript over clojure?

~~~
notduncansmith
For what GP mentioned ("systems automation") depending on the JVM (as one
would with Clojure) is kind of a non-starter, due to the long startup time. By
contrast, Clojurescript (essentially the same language, but compiled to JS
instead of JVM bytecode) can run in something like Node.js, where startup
times are considerably faster.

Edit: this new development (CLJS compiled with CLJS) is remarkable because
previously, compiling CLJS required a running JVM. One could still compile
automation scripts and run those, but that wouldn't really be true to the
"scripting" style anymore.

~~~
mfikes
You can dynamically compile and run ClojureScript scripts so long as you have
properly hooked things up to a JavaScript engine. I've started on an effort
that makes this easy OS X, wrapping JavaScriptCore and I could see similar
efforts for Node.js. Here's what I've been working on:
[http://planck.fikesfarm.com](http://planck.fikesfarm.com) It can run scripts
you have on disk, etc, and it has basic file I/O capabilities at the moment so
you can write simple text processing scripts, for example.

~~~
tbatchelli
planck is a really exciting project. What IO capabilities do you think are
missing at this point?

~~~
mfikes
Just for DX / ergonomics, I'd like to mimic more of the file I/O stuff that
you have in Clojure, especially the ability to cope with streams. And then
perhaps having network I/O would be interesting as well.

Then there is the `clojure.java.shell` namespace that could prove very useful
for scripting.

------
dominotw
I have been looking at functional languages for frontend. But, I guess I am
one of those people who just can't unsee the parentheses in lisp languages .

How does clojurescript compare to elm/purescript ?

~~~
mateuszf
You have to use it for some time, and then the parenthesis will just
disappear.

~~~
akilism
plus an editor with a nice paredit mode.

~~~
gizmo385
Having paredit makes me miss LISP when I'm not writing it. It just makes
moving around and restructuring code so much easier than it is an a C-based
language.

------
pacomerh
I've been wanting to get into ClojureScript (to clean my development
practices, etc) but I'm wondering if I need to be a Clojure user. Does it make
sense for a Javascript developer to just jump straight to ClojureScript?. I've
seen PureScript also.

~~~
freshhawk
As has been said, they are basically the same language.

In terms of learning, it's probably easier to learn Clojure at the very
beginning.

It's simpler to get repl working and get a project building with Clojure right
now. Not much simpler, but simpler. And at the very beginning, when the
toolchain is magic to you, that matters.

As early as you like you can switch to Clojurescript, learn the handful of
small differences and go from there.

~~~
akilism
It's so simple now:

[http://planck.fikesfarm.com/](http://planck.fikesfarm.com/)

download, run, and you have a clojurescript repl ready to go on osx at least.

~~~
pacomerh
nice thanks

------
netcraft
Does this mean I could use compile and then require clojurescript modules in
node? Today I use babel to "transpile" es2015 to es5 and then load those in,
could I do something similar with clojurescript?

~~~
mfikes
None of this recent work facilitates compiling ClojureScript into CommonJS
modules for use with Node.

But, the opposite is in flight: ClojureScript now has support for depending on
libraries that are packaged using the CommonJS system.

~~~
klibertp
> None of this recent work facilitates compiling ClojureScript into CommonJS
> modules for use with Node.

[http://www.matthewstump.com/misc/2012/06/04/writing-
nodejs-m...](http://www.matthewstump.com/misc/2012/06/04/writing-nodejs-
modules-in-clojurescript/)

Should be really very easy to do, you only need to study what cljs compiler
emits and the docs for Google Closure Compiler JS libs.

~~~
raju
Can someone this to me? It seems that mfikes (parent) comment, and klibertp's
comment seem to contradict each other. Not to mention the examples that
glenjamin highlighted.

I have heard similar comments in other places, in that it's not possible to
package ClojureScript as a NPM module.

Is it because of the size of the module, or something else?

------
truncate
I'm curious if ClojureScript uses the original clojure library code (eg, drop,
take, map...) or re-implements them? I tried to find something in codebase,
seems like it uses original.

~~~
swannodette
A non-trivial portion of Clojure (data structures, compiler) are written in
Java. In ClojureScript these are written in Clojure or ClojureScript so
there's really not as much to share as it would seem.

------
Turing_Machine
This is fantastic. It will be a lot easier for noobs to get their feet wet if
they can use use the full language without having to fool around with
installing a Java toolchain.

~~~
serve_yay
A while back I enjoyed going through this, also allows you to get a feel
without futzing around with tools:
[http://clojurescriptkoans.com](http://clojurescriptkoans.com)

------
agumonkey
How far clojurescript is to be clojure/js. By that I mean how close the JVM
and JS are semantically. There were discussions about that few months ago,
because of differences deep down between platforms builtin types (js integers,
etc). Swannodette also explained that cljs and clj don't share as much code as
the team would like. How much clojure code would run correctly as-is on cljs ?
Without having to use specific reader conditionals.

------
intellectable
Thanks, for all the fish ( by fish I mean awesome code ) @swannodette and
team! Can't wait to use Om Next.

Also looking forward to seeing some code examples of Demand-Driven
Architecture[0]. Does anyone know of any edifying clojure code examples?

[0] [http://www.infoq.com/presentations/domain-driven-
architectur...](http://www.infoq.com/presentations/domain-driven-architecture)

------
nextos
I wonder if one of my favorite libraries for Clojure, Anglican [1] a
probabilistic programming language, can be ported to ClojureScript without
much effort. One could do amazing things with this.

Keep up the good work. Clojure & ClojureScript are awesome.

[1]
[http://www.robots.ox.ac.uk/~fwood/anglican/](http://www.robots.ox.ac.uk/~fwood/anglican/)

~~~
rymndhng
If your library is written in pure Clojure (no reliance on Java) it's fairly
trivial with Clojure 1.7's Conditional Readers.

Here's an example of a repository that I've repurposed to compile both Clojure
+ Clojurescript.

[https://github.com/rymndhng/clj-diff/commits/add-cljc-
redo](https://github.com/rymndhng/clj-diff/commits/add-cljc-redo)

------
dgreensp
How does the output of the ClojureScript-compiler-in-ClojureScript compare to
the real thing? Do you lose the Google Closure optimizations, and if so, does
that mean it isn't a good idea to compile your web app using the ClojureScript
compiler running in Node (for example)? It's nice if you can compile
ClojureScript on a machine without Java.

~~~
gw
Correct; you do not get the benefit of Google Closure when using the
bootstrapped compiler. The JVM-based compiler will continue to be the best way
to compile ClojureScript projects for production.

------
retrogradeorbit
This is a huge milestone! I had a problem I was solving with Clojurescript six
months ago and having access to the reader would have solved it perfectly,
with lisp elegance. Instead I had to make a mess.

I think this opens huge computer science educational opportunities. Imagine a
LOGO DSL inside your browser. With all the power of cljs. I am very excited!

------
hencq
Wow, this is quite amazing! Does this also mean that we will be able to write
macros in Clojurescript?

Are there any plans to use mostly the same backend for Clojure and
Clojurescript? It seems that since the languages are almost the same, it's
only the code generation part that would be different?

~~~
mfikes
Yes and no. You can write macros for which the source is ClojureScript, but
they need to be kept separate. Here is a stab I took at explaining that
subject: [http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-
mu...](http://blog.fikesfarm.com/posts/2015-06-19-portable-macro-musing.html)

There are no plans for the same backend AFAIK.

------
bmillare
I think an article outlining the details behind the non-trivial example,
specifically on configuring how library names are resolved and how it can be
modified dynamically, would be instructive.

~~~
derek
The source code for the post is available[1], as is the macro[2] which is
loaded via XHR.

The short of it is that a load function is passed to `cljs/compile-str`, which
provides the mapping. In this case, it doesn't bother to do any mapping
because it knows that it is loading `bar.core`. However, `bar-url` could
instead be in a map from the namespace to the URL. Surprisingly simple,
actually!

1\.
[https://github.com/swannodette/swannodette.github.com/blob/m...](https://github.com/swannodette/swannodette.github.com/blob/master/code/blog/src/blog/cljs_next/core.cljs#L138)
2\.
[http://swannodette.github.io/assets/cljs/bar/core.cljs](http://swannodette.github.io/assets/cljs/bar/core.cljs)

------
DAddYE
Awesome!!! Now we want Clojure in Clojure :)

~~~
braythwayt
Doesn’t this imply the development of a JVM written in Clojure?

~~~
MBlume
Nah, A Clojure program which translated Clojure code to JVM bytecode would be
a good start.

~~~
_halgari
Like this?
[https://github.com/clojure/tools.emitter.jvm](https://github.com/clojure/tools.emitter.jvm)

------
jimmcslim
When will the module support be released? Soon I hope! Thanks for the great
work on all this.

~~~
swannodette
Module support is already in 1.7.28 however it requires a corresponding
release of the Google Closure Compiler.

------
edem
For some reason I feel like ClojureScript starts to transform into a new
Clojure dialect (which runs on node.js and not on a JVM). Am I correct?

~~~
swannodette
ClojureScript will always run on the JVM. It's just that from now on it will
_also_ always run on JavaScript.

------
likeclockwork
Hm. This allows putting functions into edn that gets sent to the browser now,
then doesn't it? Since ClojureScript can eval now?

~~~
mfikes
If you put the function source into edn and the function doesn't depend on
anything but core constructs, it would be nearly trivial to eval using the new
cljs.js.

If those functions need to call into other ClojureScript namespaces that
you've already compiled into your code then the analysis cache would need to
be populated so that eval can operate properly.

For reference, here is cljs.js/eval:
[https://github.com/clojure/clojurescript/blob/v1.7/src/main/...](https://github.com/clojure/clojurescript/blob/v1.7/src/main/cljs/cljs/js.cljs#L497)

------
avodonosov
Finally, thanks god

