Search code examples
javascriptclojurescriptread-eval-print-looprhino

ClojureScript - console and printing between browser and rhino repl


disclaimer: very new to ClojureScript

the context for the question is this file (one of the examples from "Up and Running" book with a few additions of my own). Specifically, the question is about the last two lines, you can ignore the rest.

(ns hello-compiler.hello)

(defn ^:export main []
  (.write js/document "<h1>Hello, ClojureScript compiler!</h1>"))

(defn asum [a b]
  (+ a b))

(enable-console-print!)

(println "hello.cljs loaded successfully")

the second-to-last line is necessary to make the last line work in the browser, otherwise the code generated by the CLJS-to-JS compiler doesn't know how to print things:

if (cljs.core._STAR_print_fn_STAR_ == null) {
    throw new Error("No *print-fn* fn set for evaluation environment");

, and so I need it to run the last line (the println). All of the preceding expressions get evaluated just fine, and produce the expected output, i.e. I see the greeting on the browser screen and I am able to run hello_compiler.hello.asum(2,3). With the second-to-last line, I also get the "file got loaded successfully" in the browser console.

But when I run a server-side REPL like so:

rlwrap lein trampoline cljsbuild repl-rhino

and load the file like so:

(load-file "src/cljs/hello_compiler/hello.cljs")

, I do NOT see the message in (println...). And, indeed, if I try to (println ..) from REPL manually, I get an exception:

org.mozilla.javascript.EcmaError: ReferenceError: "console" is not defined.

(it's not shown on a load-file, probably goes to some other place).

Of course, before I run the (load-file ...), I can (println ...) manually in the REPL. enable-console-print! seems to be helping in the browser, but disabling the printing in the REPL. Likewise, without that enable-console-print!, (println...) works fine in the REPL, both manually and on loading the file. It's reading pure CLJS, without compiling to JS, probably..

so the question would be - is there a way to have a setup where it works both ways? Where I can load .cljs file into the local REPL, and have the same behaviour as I see in the browser, which loads the compiled to JS version? I understand the Rhino REPL doesn't have a 'console' like a browser does, but... when I run 'node', it somehow manages to figure out what I mean by console.log =) If not, could someone please point out why me expecting such behaviour is unreasonable? Thanks!


Solution

  • OK, I think I found the answer to my own question. The more I thought about it, the more I was suspecting it's not reasonable to expect Rhino "must" have a console object which would be fine with the enable-console-print! code. So I've tried a different repl, and added [org.bodil/lein-noderepl "0.1.11"] to my :plugins. Then, with that REPL, I got everything working in the browser and in the REPL with the same code at the same time.