Embarrassingly, it took this long for me to realize there's a much tidier way to alter the reader:
Where the exception throw is for map literals with odd numbers of key-or-value items, wrap the throw in a check that counts the number of additional consecutive } tokens, stopping when it hits a non-} token, the start of the corresponding form was the wrong delimiter (not a {; throw a delimiter mismatch exception then), or the corresponding from had more than one item. Now, we have {{...{odd number of nested things}...}}, and know the nesting depth of {}s. However, there's a special case: there's a single nested thing and it's a map. In that case, we really had {{...{{even number of things}}...}}. So we bump the nesting depth by 1 and replace the map with (interleave (keys map) (vals map)) as the things-seq. Finally, if the nesting depth is greater than 1, instead of throwing the key-with-no-value exception we: * If the nesting depth is odd, drop it by 1 and replace the things-seq with [(apply hash-map things-seq)]. Throwing the key-with-no-value exception anyway, if the things-seq was odd in length. Since {{...{...}...}} with an odd number of enclosing {}s is a map nested in single-element sets. * Regardless, nest sets nesting-depth/2, each set containing the next one except the last contains the items in things-seq. The above requires only a localized change and not a massive redesign or complication of the entire reader, such as adding a whole pass. This addresses, satisfactorily IMO, the objection based on not wanting to elevate the reader's complexity. The objection of multiple representations being "confusing" is moot when so many other things in Clojure also have multiple representations at a low level. That leaves the objection that it may be harder for *people* to read, since they have to reach the end of nested {{{s to figure out what the data structure is. I answer that by noting that it's possible to write poorly-readable code in any language worth coding in, including the existing version of Clojure. Someone who wants their {{...}} sets to be easily parsed by humans is advised simply to a) not nest lots of single-element sets (that ought to be damned rare anyway), b) not put spaces between the braces in {{ and }}, and c) put spaces between {{ and adjacent {s and between }} and adjacent }s. So, if you really had to nest a map in two sets and wanted to not use #{...}, you'd want {{ {{ {k1 v1 k2 v2} }} }}, so the delimiter units are easily separated. IDE support could also help, parsing according to the stated rule and treating a (balanced, with all internal delimiters also balanced) {{ ... }} pair as two single delimiters that are {{ and }} rather than four that are two {s and two }s for the purposes of "highlight matching delimiter" functionality (the braces in {{ and }} would highlight together) and rainbow parens (the paired {{ and }} would be a single color). (Paredit would have to not change behavior, or if you typed {{ intending to add items and then }, more items, and }, it might not let you break up the }} it made corresponding to the {{.) The pretty printer would also benefit from putting spaces between paired braces and adjacent braces that face the same way, keeping the grouping clear. So ... any further objections, other than "it's unlikely anyone cares enough to bother actually making such a change"? :) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en