4
votes

Once the browser is connected to the clojurescript repl, I previously had no way of calling macros from the repl. This is an issue that has put me off clojurescript in the past, preferring using javascript directly. Basically, I felt that the cljs-repl was kinda lame and I was going back to the compile/debug cycle that writing code in clojure was supposed to emancipate us from.

Are there any good workarounds/workflows for pushing and testing code in clojurescript? Especially if macros can be evaluated?

An example of my problem is:

  1. make a new cljs project

    lein new cljs-template blah

  2. start up the server

    cd blah

    lein run

  3. run the web-repl

    lein trampoline cljsbuild repl-listen

  4. there is a file src/blah/client/main.cljs with the heading

    (ns blad.client.main
      (:require [noir.cljs.client.watcher :as watcher]
                [clojure.browser.repl :as repl]
                [crate.core :as crate])
      (:use [jayq.core :only [$ append]])
      (:use-macros [crate.macros :only [defpartial]]))

notice the line (:use-macros [crate.macros :only [defpartial]])

I can't use defpartial in the browser repl because it is a macro. The error I get is:

>> (crate.macros/defpartial [])
"Error evaluating:" (crate.macros/defpartial []) :as "crate.macros.defpartial.call(null,cljs.core.Vector.fromArray([]));\n"
#
TypeError: Cannot read property 'defpartial' of undefined

Now defpartial is quite a useful macro and without it, it was a hassle.

My problem got worse when i wanted to define another macro in the project with the :use-macros. I could not debug what i wrote at all in the repl or the browser and after about half a day, I figured out that it was quicker to use a clj repl, test the macro in there using macroexpand and the copy the results back into the browser repl. I got one cljs macro working after about a day it wasn't very fun. This was about 6 months ago. I'm hoping there is a quicker way to do this now.

2
I'm not sure I understand the question. You can certainly evaluate macros from the browser REPL. Do you mean you want to be able to define macros at the REPL? - levand
Ok, yes, I've verified that this is an issue. It's a problem with the way the browser REPL is implemented rather than ClojureScript itself, I think. I know the author of the bREPL and will check with him to see if he knows of a way around the problem, and post a proper answer based on that. In the meantime, I'd recommend writing a non-macro version of defpartial. This is almost always possible, just pass an anonymous function instead of raw forms. It's syntactically uglier but it works (unless you need to actually short-circuit evaluation, but that doesn't seem to be the case here) - levand
I'm pretty sure that the reason is that macros are expanded before the .cljs code is compiled. if there was a way to say compile and insert the macro on the fly in emacs or another editor, that would solve the problem. I was hoping maybe someone has written something already - zcaudate

2 Answers

6
votes

In order for macros to be loaded during an interactive session w/ bREPL you need to explicitly evaluate the ns form in bREPL first.

Even so this is a bit annoying - some work has landed in master to support interactive macroexpansion but it needs more work. W also have a few ideas floating around about making bREPL more useful by doing analysis of the source files on startup.

3
votes

Today I have checked that with cemerick/austin: a clojureScript browser-REPL, you can use and evaluate your macros in the brepl without limitation, that's to say without explicitly evaluate the ns form in bREPL first. I'm using in this demo-project core.async macros and custom domain macros without problem.