“Interpreted” hiccup with shadow-grove

(This is about shadow-grove.) I read in the docs that:

“Interpreted” hiccup won’t be enabled by default but it is easy to support.

And it makes me wonder if there be some (easy?) trick required to do what I will explain next.

What I want to accomplish is to create a fragment that takes a string as input, as in:

(<< hiccup)

Where hiccup is the output of (cljs.reader/read-string hiccup-str). (I do hope I am making sense here.)

As a sanity check, it works if I write:

(<< [:div "hello"])

But if I write the following, I get an error:

(<< (cljs.reader/read-string "[:div \"hello\"]"))

(And the error says something like this: No protocol method IConstruct.as-managed defined for type cljs.core/PersistentVector: [:div "hello"]).

Now I suspect I can figure this out, but I have a strange sense that it may be of value to others to put this out there.

Interpreted mode is enabled by adding shadow.arborist.intepreted to your ns :require in your main namespace (the one with :init-fn). The require is all you need, after that it’ll understand regular hiccup.

1 Like

I can’t believe it: is it that easy? I can confirm that it certainly works!

I wonder: does this incur a performance hit everywhere that << is used, or only when interpretation is necessary?

Yes, that easy. No performance impact on <<.

Except for the cases where you forget (<< [:div "static hiccup"]) and just do [:div "static hiccup"] instead. Normally this will throw an error, now it won’t and just be slow-ish. How much slower actually depends on the structure, but the more elements it processes the larger the gap becomes.

That is also the reason this isn’t enabled by default. Falling back to interpreted mode can be very hard to spot, and as such lead to performance death by a thousand cuts. It might also not be ideal for the problem you are trying to solve currently, but it certainly works fine. Just avoid rendering your entire app that way every frame :wink:

1 Like

I’m exaggerating a lot here.

Interpreted mode is actually fine, and sort of within reagent performance for the most part. I didn’t optimize this at all yet, but that would be the baseline. A lot of people have built performant-enough things with reagent, so the interpreted mode is certainly good enough for most things. I just happen to care about performance a little too much myself.

1 Like