Planck Road Ahead

January 22, 2017

Planck 2 is currently in beta, and is closing in on a release. The main feature in Planck 2 will be support for Linux and there will be a future blog post about that aspect.

In the meanwhile, I wanted to describe a few of the new features in Planck 2 relative to Planck 1.17.

Async Shell

Thanks to contributions by Jonathan Leonard, the namespace gains the ability to execute long-running shell commands, calling back when complete.

cljs.user=> (require '
cljs.user=> ( "sleep" "30" prn)
cljs.user=> ;; 30 seconds go by
{:exit 0, :out "", :err ""} 

This can be extremely useful when writing scripts given the lack of threads in ClojureScript.

Hi-Res Timer

In Planck 1.17, cljs.core/system-time is at millisecond resolution:

cljs.user=> (system-time)
cljs.user=> (time (apply + (range 1e7)))
"Elapsed time: 17.000000 msecs"

Planck 2 monkey-patches cljs.core/system-time with native code returning nanosecond-resolution timestamps:

cljs.user=> (system-time)
cljs.user=> (time (apply + (range 1e7)))
"Elapsed time: 16.948683 msecs"

Interrupt Forms Generating Output

If you evaluate something like (range) in a ClojureScript REPL, you are pretty much done. In Planck 1.17, because it is using Fipp, you at least get a stream of integers being printed.

In Planck 2, you can interrupt this stream by hitting Ctrl-C, and you will be returned to the REPL prompt with all of your REPL state intact:

cljs.user=> (def a 3)
cljs.user=> (range)
cljs.user=> a

This mechanism doesn't work for forms that don't generate any printed output, like (apply + (range)). This is because it hooks into the underlying print call to check for Ctrl-C—and thanks to Fipp, large forms result in multiple print calls.

This has been one of my favorite new features. I've found it to be useful surprisingly often: It works for large output forms (not-necessarily infinite), and I suppose I'm impatient at times, and just want to get back to the REPL prompt.

Source for REPL-defined forms

In Planck 1.17, the source REPL special only works for def forms that exist in namespaces that are loaded from source (either on disk, or JARs, or bundled with Planck).

Planck 2 extends this capability to forms interactively entered at the REPL:

cljs.user=> (defn square
       #_=>  [x]
       #_=>  (* x x))
cljs.user=> (square 3)
cljs.user=> (source square)
(defn square
 (* x x))

This works even if you redefine a def that came from source (showing your REPl-entered definition). And, in that case, if you subsequently require the namespace, passing the :reload flag so that the def reverts to the on-disk form, source will reflect that.

Planck Classpath Environment Variable

If you have libraries that you frequently use, you can put them in PLANCK_CLASSPATH and they will always be available, unless specifically overidden by -c.

I find this useful in order to always have Andare always available in order to mess with core.async or a locally-built copy of the port of test.check to self-hosted ClojureScript available for use when messing with spec.

Trying it Out

If you'd like to try Planck 2 before it is released, on macOS, just do

brew install --devel planck

On Linux it is fairly easy as well, just clone the repo, ensure you have the needed deps, and build it:

cd planck
Tags: Planck ClojureScript Bootstrap