When launching Planck using plk
, you can specify a vector of source directories in deps.edn
:
{:paths ["src" "test"]}
With this, you can put this code in src/foo/core.cljs
:
(ns foo.core)
(defn square
[x]
(* x x))
Then, if you launch Planck via plk
$ plk
you can then load the code in foo.core
by doing
cljs.user=> (require 'foo.core)
If you subsequently edit src/foo/core.cljs
, say, to define a new function, or to change existing functions, you can reload that code by adding the :reload
flag:
cljs.user=> (require 'foo.core :reload)
Alternatively, when launching Planck you can use the -c
or --classpath
option, or the PLANCK_CLASSPATH
environment variable, to specify a colon-delimited list of source directories and JARs to search in when loading code using require
and require-macros
. You can also use -D
or --dependencies
provide a comma separated list of SYM:VERSION
, indicating libraries to be loaded from the local Maven repository. (See the Dependencies section of this guide.)
Using -c
, you can specify "src"
and "test"
as source directories via
planck -c src:test
If you define macros in bootstrap ClojureScript (which is the mode that Planck runs in), the macros must be written in ClojureScript (as opposed to Clojure, as is done with regular ClojureScript).
Even though the macros are defined in ClojureScript, they are defined in *.clj
files. You can, if you wish, also define macros in *.cljc
files, but when they are processed, the :cljs
branch of reader conditionals will be used.
When writing macros for self-hosted ClojureScript, they must abide the same rules that apply to all ClojureScript code. In particular, this means a macro cannot call another macro defined in the same compilation stage: If a macro calls another macro during expansion, then one approach is to define the called macro in a “higher” namespace (possibly arranged in a tower). On the other hand, if a macro simply expands to a call to another macro defined in the same namespace, then the compilation staging rules are satisfied.
If an exception is thrown, you may see a stack trace. (If not, you can use pst
to print the stack trace for an exception.) When trace lines correspond to code that originated from files, the line numbers are mapped from the executed JavaScript back to the original ClojureScript.
Planck supports tagged literals. For an overview of this feature see the Tagged Literals documentation.
Planck searches for data_readers.cljc
files at the root of the classpath, and the values of the data reader maps are associated with vars that must defined in ClojureScript.
For example, lets say a data_readers.cljc
file contains:
{foo/bar my.project.foo/bar}
Then, in order to parse #foo/bar [1 2 3]
, #'my.project.foo/bar
must be defined in ClojureScript. (This differs from JVM ClojureScript, where this must be defined in Clojure.) This could be accomplished by defining a namespace like the following that is loaded into Planck before expressions involving #foo/bar
are read.
(ns my.project.foo)
(defn bar [x] ,,,)
Note that, in either case (JVM ClojureScript, or self-hosted ClojureScript), the reader function bar
above must return code that is compilable in ClojureScript.
It is possible to make use of the cljs.js
namespace within Planck. But, since Planck is built with the :dump-core
ClojureScript compiler option set to false
, calls to the 0-arity version of cljs.js/empty-state
will produce a state atom which lacks cljs.core
analysis metadata. To produce a populated compiler state atom, you can make use of planck.core/init-empty-state
:
(require 'cljs.js 'planck.core)
(def st (cljs.js/empty-state planck.core/init-empty-state))
(cljs.js/eval-str st "(map inc [1 2 3])" nil
{:eval cljs.js/js-eval :context :expr} identity)