(1) Good idea?
(2) What should it be named?
Stuart
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
~@cls
: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
Am 03.12.2008 um 20:51 schrieb Meikel Brandmeyer:
> cls (mapcat (fn [[x c]] `[(~xprd ~xndl ~x) ~c]) (partition 2
> cls))
> xndl (gensym "condp_needle__")
> xprd (gensym "condp_predicate__")
Oops. These should of course be changed to be in the
right order.
Sincerely
Meikel
Am 03.12.2008 um 21:10 schrieb Brian Doyle:
> Can you include an example usage of this function? Thanks.
(condp = x
1 "We got a one."
2 (str "We got a " (- 3 1))
"We got something else."))
Sincerely
Meikel
Am 04.12.2008 um 10:44 schrieb Meikel Brandmeyer:
>> I almost whipped this up yesterday, but I got sidetracked thinking
>> about how best to provide a feature like Scheme's cond's =>. Do you
>> know it? It feeds the value of the test to the fn on the rhs of the
>> clause. It can be useful.
It seems my patch is completely needless: In contrib
there is already cond-let, which does what you want.
Sincerely
Meikel
I reworked my initial proposal according to the comments
of Rich. The syntax now looks as follows:
(condp predicate expr
test-expr result-expr
test-expr :> result-expr
...
default-expr)
A result-expr is chosen according to (predicate test-expr expr).
In the first form, result-expr is simply evaluated and the result
is returned. In the second form, result-expr is expected to
evaluate to a function. This function gets passed the return
value of the predicate call. Whatever the function returns
is returned by condp.
If no test-expr leads to a success the default-expr is evaluated
and the result returned. If no default-expr is supplied an
exception is thrown.
The patch is attached at the issue tracker.
http://code.google.com/p/clojure/issues/detail?id=6#c2
Comments appreciated.
Sincerely
Meikel
What is ":>"? Is that just a keyword whose name is ">"? I think adding
more characters with special meaning makes code harder to read, so I
hope we don't add more of these.
> ...
> default-expr)
>
> A result-expr is chosen according to (predicate test-expr expr).
> In the first form, result-expr is simply evaluated and the result
> is returned. In the second form, result-expr is expected to
> evaluate to a function. This function gets passed the return
> value of the predicate call. Whatever the function returns
> is returned by condp.
>
> If no test-expr leads to a success the default-expr is evaluated
> and the result returned. If no default-expr is supplied an
> exception is thrown.
>
> The patch is attached at the issue tracker.
> http://code.google.com/p/clojure/issues/detail?id=6#c2
>
> Comments appreciated.
>
> Sincerely
> Meikel
>
>
--
R. Mark Volkmann
Object Computing, Inc.