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

Reply via email to