[racket-dev] Square-bracket-sensitive macros in Scribble sandboxes
I've pretty much made up my mind on this, so please don't feel like you
have to take time to respond point-by-point. Unless you've seen a gaping
hole in my reasoning, anyway, then by all means, have at it.
On 11/26/2012 05:41 PM, Eli Barzilay wrote:
> Two hours ago, Neil Toronto wrote:
>> For example, it's common to have arrays of Indexes, or (Vectorof
>> Index), which would have to print like this with implicit quoting:
>>
>> (array `#[,'#(0 0) ,'#(0 1)])
>>
>> Just working out the algorithm to print such a thing made me want to
>> curl up and whimper.
>
> Three sidenotes:
>
> 1. You probably mean (array `#[,`#(0 0) ,`#(0 1)]), right?
The inner quasiquotes can be quotes because #(0 0) and #(0 1) are
vectors, not array rows. If they were array rows, they still shouldn't
need to be quasiquoted. Well, depending on design...
Array rows don't exist as separate objects (an array is just a
function), so I have a hard time intuiting what it means to quote the
inner ones. But here are some (just some) design options:
1. Allow a quote just on the outer "#[...]" and have it apply to all
nested "#[...]".
2. Allow a quote on the outer "#[...]" and have it apply to all
nested "#[...]", but allow them to override with their own quotes.
3. Allow quotes at any level, unpropagated.
4. Avoid difficulty altogether by having array syntax not quote
its elements.
#1 might be easy. #2 might be cool, but complicated. #3 is kind of
weird, and I think it means the only quotes that matter are the
innermost. For all of these, there are additional design options. For
example, for #3, should quasiquoting outer rows be necessary if you want
to quasiquote inner ones? For #2, how would one spell "override" in a
way that distinguishes it from "element"?
#4 avoids all these choices, and that's what is currently implemented.
> 3. And besides, doing such algorithms is usually easier than it
> sounds. (And IME, they're a perfect example where developement
> with test cases makes things way easier...)
I'm okay with inventing apparently complicated recursive algorithms that
eventually come down to a few well-chosen rules. (That's language
semantics in a nutshell.) My problem has been *coming up with the test
cases* for the various options I listed above.
Now, I know where your brain just went, so let me head it off. You were
about to reply with a bunch of starter test cases or a load of helpful
hints. (Because that's who you are... and I appreciate it!) Let me make
a case for not developing another set of array parsing/printing
algorithms first, starting with your example:
> For example, I'll need to write something like
>
> (define (±1 i)
> (array `#(,(sub1 i) ,i ,(add1 i))))
>
> make it return a 3x3 array, and you get some less convenient thing
> like
>
> (define 1- sub1)
> (define 1+ add1)
> (define (±1 i j)
> (array `#(#(,(list (1- i) (1- j)) ,(list i (1- j)) ,(list (1+ i) (1- j)))
> #(,(list (1- i) j ) ,(list i j ) ,(list (1+ i) j ))
> #(,(list (1- i) (1+ j)) ,(list i (1+ j)) ,(list (1+ i) (1+ j))))))
I wouldn't want to write that, either. Right now, you'd write
(array
#[#[(list (1- i) (1- j)) (list i (1- j)) (list (1+ i) (1- j))]
#[(list (1- i) j ) (list i j ) (list (1+ i) j )]
#[(list (1- i) (1+ j)) (list i (1+ j)) (list (1+ i) (1+ j))]])
The vector syntax just delimits rows; it never quotes. Square parens
aren't required, but make rows easier to distinguish. Arrays' custom
printers print square parens, which gives feedback when a user is
confused about whether #(...) means a row or a vector-valued element.
Quotes and quasiquotes stop the `array' macro's recursion into rows, so
quotes always mean "this is an element". For example, this is a
zero-dimensional array that contains a vector:
(array '#(0 1 2 3))
Here are my reasons for leaving it as it is:
* Most array elements will be self-quoting anyway (numbers, strings,
other primitive types).
* It's easy enough to remember the exception "quote literal vectors".
Also, Racket's printer writes an explicit quote before literal
vectors, so arrays of array indexes parse and print the same.
* I'm having a hard time with test cases for implicitly quoted array
rows, which means math/array users would probably have a hard time
reasoning about it as well.
* There are enough possible design choices that give rise to similar-
but-subtly different behavior that it would be easy for users to
get confused about the actual rules.
At any rate, I'm all for simple. Thanks for hashing this out with me.
Neil ⊥