On 17 Mar 2003, Sam Steingold wrote:
> * #(x1 x2 x3 ... xn) may be interpreted to mean (apply #'vector `(x1 x2
> x3 ... xn)).
> #1A is not mentioned. I suggest raising this on c.l.l.
> personally, I would rather signal an error here, like CMUCL and
> unpatched CLISP (ACL? LW?) do because
> - when you write a literal, your would write #() anyway, so the simple
> user does not lose
> - when you generate the form, you should make sure that the dim is 1
> anyway, so you can use #() just as well
> - when the user sees that `#1A(1 2 ,a 4) works but `#2A((1 2) (,a 4))
> does not, the user would be rightfully surprised; he will also think
> that `#2A(,a ,b) should work when a and b are sequences of the same
> length &c &c...
Okay, how about dividing the work into three milestones.
Basically I have taken care of most of the first milestone already:
optimization, proper i18n-able error messages using TEXT macro,
system builds itself cleanly. What's left is beating up the backquote
with lots of nasty test cases.
In the second milstone, I can put in rudimentary support for
backquoting over multi-dimensional arrays. This means that no special
reader is used. A form like
#2A((,@x ,y) (,z))
will basically be read to produce the object.
#2A(((SYSTEM::SPLICE X) (SPLICE Y) ((SPLICE Z))))
This will be supported in a straightforward way. The algorithm is:
walk the leaf row vectors of the array and perform the backquote
substitution on them in the straightforward way. Then spin these
expanded row expressions into a big MAKE-ARRAY constructor call.
Conceptually, this is like distributing the ` operator into the rows,
in other words:
`#nA( .. ( ... (...) (...) (...) ... ) ... )
will be treated something like:
#nA(... ( ... `(...) `(...) `(...) ... ) ...)
except that evaluation of the unquotes within `(...) is arranged. This
means that syntax like #2A(,@form) will not work, because the unquote
is at the wrong level; the form must have the required shape for a
two-dimensional array, and the unquotes must appear in the innermost
In the third milestone, we can work in unrestricted unquoting, such as:
(let ((rows '((1 2) (3 4) (5 6))))
`#2A(,@rows)) ;; splice in all the rows.
==> #2A((1 2) (3 4) (5 6))
This, of course, requires cooperation from the #A reader macro. In
fact, it will probably be necessary for the backquote implementation
to temporarily overrides the read table with its own reader.
I think there is value in being able to do unquoting over arrays,
even if it's not portable.
For instance, suppose you want to make a rank 3 matrix with some
non-zero eigenvalues on the diagonal, and zeros elsewhere:
(let ((e1 3) (e2 4) (e3 5))
`#2A((,e1 0 0)
( 0 ,e2 0)
( 0 0 ,e3)))
==> #2A((3 0 0) (0 4 0) (0 0 5))
This elementary substitution is possible just with milestone 2