ClojureScript (Min)

I've been starting a project to see how much of ClojureScript I can use and get it to compile to extremely small sizes.

A "hello world" app in ClojureScript, just console logging that string, will result in just a few lines of code. The trick is to avoid anything that pulls in a lot of the core types, like all the immutable data structures ClojureScript defines. These immediately bloat up the code, with the protocols etc etc.

So far I've identified the following as problematic

Why they don't work

reify

This is an interesting one because what happens is extremly subtle. See below the macro expansion for reify:

cljs.user=> (macroexpand '(reify))
(do (cljs.core/when-not (cljs.core/exists? cljs.user/t_cljs$user21417) (cljs.core/deftype t_cljs$user21417 [meta21418] cljs.core/IWithMeta (-with-meta [_21419 meta21418] (new t_cljs$user21417 meta21418)) cljs.core/IMeta (-meta [_21419] meta21418))) (new t_cljs$user21417 {}))

Notice all the way at the end there is a an empty map? This is because reify (which I learned in the process of debugging this) implements IWithMeta and IMeta, and will transfer the meta from the form (for example, ^{:key :val} (reify)) to the resulting instance. But, if no meta is defined it apparently falls back to an empty map. I feel like it's better to have this as nil instead, since it solves my problem and also is more what you'd expect when no meta is defined on something.

deftype and Object

Something weird I found, at least with shadow-cljs (need to confirm in ClojureScript), is that some method names cause inference errors. For example, naming a method findAll, allTodos or todos causes issues, where naming it all does not. This has been fixed after bringing up the issue in the shadow-cljs Clojurians Slack.

Libraries

It occurred to me that having core.async would be really invaluable in building things. I think I will look into forking it and converting all the Clojure types into js types.