[alexandria-devel] Re: Review cycle 2: SWITCH, ESCWITCH, and CSWITCH
Nikodemus Siivola
nikodemus at random-state.net
Sun Jun 8 22:13:11 UTC 2008
Ok. Here's my take in addressing the issues. I am not 100% happy with
the docstrings, but can't seem to do better right now. If someone else
feels up to it, input much appreciated.
Notable differences aside from the docstrings:
1. :TEST and :KEY syntax:
(switch (foo :test test)
(bar :bar))
means to test with (FUNCALL TEST #:VALUE BAR), not (TEST #:VALUE BAR).
2. NIL as :KEY is the same as identity, as usual.
I additionally considered getting rid of T as a special clause marker,
but I suppose paralleling CASE &co makes sense. I adjusted the tests
to the new syntax, but more tests still need to be added.
As for the fallthrough/multiple keys issue: something like this can be done:
(switch (foo :test (lambda (x y) (member x y :test #'equal)))
('("foo" "bar") ...)
(...))
but it is ugly as hell. Not sure about what to do. Re. expanding into
COND: I think the API is the important bit. If we are able to figure
out that something else is more efficient, then we can expand into
something else -- COND is an implementation detail.
Here are the new (proposed) docstrings:
macro switch (&whole whole (keyform &key (test #'eql) key) &body clauses)
"Conditionally executes one of the clauses, and returns its values. KEYFORM
is first evaluated, and if KEY is given and non-null, it is used to extract a
comparison value from the result of evaluating KEYFORM.
Clauses are of the form:
(CLAUSE-KEY &BODY CLAUSE-FORMS)
Each clause is tested in turn. The first clause for which
(FUNCALL TEST COMPARISON-VALUE CLAUSE-KEY)
evaluates to true has its CLAUSE-FORMS executed as an implicit PROGN, and the
values returned. No further clauses are executed.
If no clause matches, and the final clause has the symbol OTHERWISE or T as
its CLAUSE-KEY, it is executed. If no OTHERWISE clause exists, NIL is
returned.
To use T as a regular CLAUSE-KEY, quote it:
(switch (foo)
('t 1)
(t 0)) ; evaluates to 1 if FOO evaluates to T, and 0 otherwise."
macro eswitch (&whole whole (keyform &key (test #'eql) key) &body clauses)
"Conditionally executes one of the clauses, and returns its values. KEYFORM
is first evaluated, and if KEY is given and non-null, it is used to extract a
comparison value from the result of evaluating KEYFORM.
Clauses are of the form:
(CLAUSE-KEY &BODY CLAUSE-FORMS)
Each clause is tested in turn. The first clause for which
(FUNCALL TEST COMPARISON-VALUE CLAUSE-KEY)
evaluates to true has its CLAUSE-FORMS executed as an implicit PROGN, and the
values returned. No further clauses are executed.
If no clause matches, an error is signalled."
macro cswitch (&whole whole (keyform &key (test #'eql) key) &body clauses)
"Conditionally executes one of the clauses, and returns its values. KEYFORM
is first evaluated, and if KEY is given and non-null, it is used to extract a
comparison value from the result of evaluating KEYFORM.
Clauses are of the form:
(CLAUSE-KEY &BODY CLAUSE-FORMS)
Each clause is tested in turn. The first clause for which
(FUNCALL TEST COMPARISON-VALUE CLAUSE-KEY)
evaluates to true has its CLAUSE-FORMS executed as an implicit PROGN, and the
values returned. No further clauses are executed.
If no clause matches, a continuable error is signalled."
Complete diff attached.
Cheers,
-- Nikodemus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: switch.patch
Type: application/octet-stream
Size: 8140 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/alexandria-devel/attachments/20080609/6629d84a/attachment.obj>
More information about the alexandria-devel
mailing list