> These functions are a documented way of requesting a map of a particular type
D'oh! You're right.
> we might want to introduce an obj-map
I see you did just that with CLJS-322 – nice.
> the story might well be different if we were to introduce some generic factory functions
There are already some generic factory functions. 'set, for example, is documented as "Returns a set of the distinct elements of coll." despite always returning a PersistentHashSet. Similar for vector and some others. It seems like map is the only core data structure that realistically has several reasonable choices for a default representation.
> implementing a bunch of compiler macros around those new factories and letting them handle data structure literals would save some duplicate work
So all this was somewhat inspired by tagged_literals.clj – You'll see that those functions are effectively macros which take a form and, generally, return an invocation form.
In my mind, I see Clojure's sugar syntax as a strict expansion transformation.
For example, ^:m {:x [@y 'z/w true]} is simply a shortcut for:
(with-meta (make-map (keyword "x") (vector (deref y) (symbol "z" "w") Boolean/TRUE)) (make-map (keyword "m") Boolean/TRUE))
This sort of thing already happens for @ derefs, # lambdas, etc.
In theory, this could be implemented at a level lower than the compiler. You could, for instance, define a reader "desugar" mode which only returns lists and primitives instead of vectors, maps, etc. This would greatly reduce the number of special forms in the compiler, since all of these boil down to invocations with macros.
Emit methods could be replaced with macros for at least these things: vars, maps, vectors, sets, nil, bools, regexes, keywords, symbols, metadata, and empty lists.
The result would be a significant reduction in the amount of code in the compiler for a proportionally smaller increase in the amount of code in per-language macros and maybe the reader.
> I have a feeling this is an issue best decided once there actually are multiple backends in place
I'll grant you that.
I've said my piece on the topic and don't feel very strongly about this particular patch. I just wanted to spark the discussion about reusing more bits of the compiler between backends. In my mind, it's almost always preferable to transform lists than it is to emit strings. I tried that, and the result was a reduction in responsibilities for the analyzer and macros that were easier to work with than emit methods.
I'd also like to extend this for Symbols and Keywords.
I've been experimenting with fleshed out Symbol and Keyword objects with interning. I've found that I need emitters, macros, and functions. With the approach here, I could eliminate the emitters and instead have the analyzer produce invocation forms.