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



Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to