lbradstreet / instaparse-cljs

Port of Instaparse to Clojurescript
89 stars 4 forks source link

side-effecting transformations work in Clojure but not ClojureScript #19

Open yatesco opened 8 years ago

yatesco commented 8 years ago

Hi,

So I am a bad developer :-), and when I transform the tree I include some side-effecting transforms which mutate external state. The transforms return nil.

In Clojure this all works, in ClojureScript it 'partly' works. Specifically only the first two side-effecting children work, the rest of the side-effecting siblings are ignored.

My actual use-case is for parsing dates which might produce the following sequence:

[:S
  [:date
   [:dateDay [:strictNumbers [:strictNumber "1"]]]
   [:dateMonth [:strictNumbers [:strictNumber "1"]]]
   [:dateYear [:dateFullYear "2018"]]]]

I have a defn which returns the transformations map and closes over a mutable js/Date. The three dateX transformations mutate that date accordingly setting the day, month or year. The date transform receives the sequence of nils and simply returns the milliseconds between now and the mutated date.

This works fine in Clojure but in ClojureScript only the first 2 (TWO) children of the :date sequence are evaluated.

The 'fix' is simply to put a (dorun args) in the :date transformation. I expect most people don't see this as their transformations probably combine the children transformations and hence force evaluation.

So yeah, as I say, I am a bad developer :-) but there is a reason I am doing it this way. It didn't strike me as unreasonable to expect this to work, and it does indeed work in Clojure.

The fact it evaluates the first two children made for an interesting day debugging why ;-). If none of the siblings worked then that would have gotten me there much quicker and a quick scan through the code doesn't indicate an obvious place that forces the evaluation of the first two siblings.

If this isn't clear I can cobble together a test project.

That's all - and thanks for Instaparse, it has bought all the power of the excellent antlr to Clojure(Script) :-)