Closed 3b closed 11 years ago
I don't think OR returning a list would be right: that would just make it harder to determine which leg was matched.
Adding ENSURE-LIST to :DESTRUCTURE seems like a better option, but I'd like to see a real use-case first.
Note that you can also always wrap a single item in an AND:
(or (and "foo") (and #\b #\a #\r))
in which case a list is returned in both cases.
ensure-list
in :destructure
wouldn't be quite right, since it would still destructure differently depending on whether the matched subrule returned a list or an atom. Similar problem with wrapping the single items in AND
. Rather than using ensure-list
I think :destructure
would need to check for OR
rule, and always wrap it in a list in that case.
Wrapping the whole OR
in AND
or using :lambda
instead of :destructure
are valid workarounds, but it would still be nice to not need to think about it.
For real use cases, see most of the uses of :lambda
(atx-start
, source
, source-contents
, etc.) in 3bmd/parser.lisp, which would probably all have used :destructure
instead of :lambda
otherwise.
I don't see how ATX-START or SOURCE-CONTENTS would benefit from :DESTRUCTURE. The first seems fine as it is, and the second would really like to use just (:CONCAT T).
SOURCE is a bit nasty, agreed.
I'm a bit wary about making the transform construction too smart, though.
Maybe the indication here is that OR uses should be structured so that all possible productions have the same form?
Eg. for SOURCE something like
(defrule source (or bracketed-source source-contents)
(:function identity))
(defrule bracketed-source (and "<" source-contents ">")
(:destructure (b1 text b2)
(declare (ignore b1 b2))
text))
?
WONTFIX, I guess.
OR
forms return a single item, which tends to break thedestructuring-bind
if it is an atom, or binds confusingly (if at all) if it happens to match a more complicated subrule which returns a list.Not sure if it would be better to add a special case to
:destructure
, or ifOR
should always return a list.(parse 'foo-bar "foo")
errors withThe value "foo" is not of type LIST.
while
(parse 'foo-bar "bar")
errors witherror while parsing arguments to DESTRUCTURING-BIND: invalid number of elements in ("b" "a" "r") to satisfy lambda list (A):