Hi Stuart and Rich, Am 03.12.2008 um 19:00 schrieb Stuart Sierra:
I'm pretty sure I don't like the sound of that at all. We had a nice discussion about fcase/condf, which I'd like to get in, here:http://groups.google.com/group/clojure/browse_frm/thread/ dee910bef629...And I haven't forgotten about that, just haven't had time to work on it. Anyone else who wants to tackle it is welcome.
How about the following: (defmacro condp"condp compares the given needle with the first clause using the given
predicate. In case the predicate returns true the second clause is
returned. Otherwise condp goes on with the rest of the clauses. In
case there is an odd number of clauses the last one will be returned
if no preceding clause matched. If no default clause is given an
exception is thrown. The predicate is called with needle as first
argument and the first clause as second argument."
[pred needle & clauses]
(let [c (count clauses)
par (rem c 2)
cls (take (if (zero? par) c (dec c)) clauses)
cls (mapcat (fn [[x c]] `[(~xprd ~xndl ~x) ~c]) (partition 2
cls))
xndl (gensym "condp_needle__")
xprd (gensym "condp_predicate__")
lst (if (zero? par)
`(throw (Exception. (str "No condp clause matched for: "
(prn-str ~xndl))))
(last clauses))]
`(let [~xprd ~pred
~xndl ~needle]
(cond
[EMAIL PROTECTED]
:else ~lst))))
I mulled about the (x _) syntax, but to be honest: I think #() is
perfectly sufficient. We would need to quote all the contents to
prevent multiple evaluation, but then we have to recurse and check
for _ vs. non-_...
I expect the predicate to be a function of two arguments with the first
being the needle and the second being the clause, we compare to.
Predicates where order doesn't matter or the order agrees may be simply
used. Others or more complicated expressions can be wrapped in a #().
Here we still have a problem for #(pred (complicated-computation) %2
%1)....
In case the number of clauses is even, and no clause matched the
predicate, we throw an exception. In case the number of clauses is
odd, we return the last one as default. I think adding a simple nil
is tolerable, making the "I ignore a failed run" explicit.
What do you think?
Sincerely
Meikel
smime.p7s
Description: S/MIME cryptographic signature
