2009/7/3 Christophe Grand <[email protected]>:
> Hi all!
>
> On Thu, Jul 2, 2009 at 11:09 PM, Laurent PETIT <[email protected]>
> wrote:
>>
>> (def push conj)
>> (def closing-counterpart { \( \), \[ \] })
>> (def opening-char? closing-counterpart)
>> (defn matching-pair? [left right] (= right (closing-counterpart left)))
>>
>> (defn consume-one [stack c]
>> (if (or (opening-char? c)
>> (not (matching-pair? (peek stack) c)))
>> (push stack c)
>> (pop stack)))
>>
>> (defn balanced? [s]
>> (empty? (reduce consume-one [] s)))
>>
>> (defn main []
>> (apply print (map balanced? *command-line-args*)))
>>
>> (when *command-line-args*
>> (main))
>
> I think you don't need opening-char?
>
> (defn balanced? [s]
> (let [tr {\( \) \[ \]}]
> (empty?
> (reduce #(if (= (peek %1) %2)
> (pop %1)
> (conj %1 (tr %2))) [] s))))
>
> I push "transposed" characters on the stack, thus only \] \) or nil can be
> on the stack.
> Since nil isn't equal to a character, it will never be popped and thus it
> ensures the stack will not be empty.
>
>
>>
>> It's the second time I wish I had a version of reduce that allows to
>> quit the reduction early.
>
>
> You're not alone Laurent but I'm not sure that's a simple reduce-while is
> possible (I can't decide which values to test for early exit (accumulated
> result or accumulated result + item) and when (before or after calling the
> reducing function)).
Indeed, not easy to be general, concise and elegant at the same time here ...
What about:
"(reduce-until pred reductor init-acc coll)" ?
pred would be a function of acc (the accumulator) and i (next item from coll),
be executed before reductor,
and return
* nil or false for continuing,
* a vector with a specific return value (which could be acc or something else)
* special meaning keyword :next for reduce-until to return the final
call of reductor on acc and i (this one could be got rid of, though ?)
e.g. :
my version would become
(defn consume-one [stack c]
(cond
(opening-char? c) (push stack c)
(matching-pair? (peek stack) c) (pop stack)))
(defn balanced? [s]
(empty? (reduce-until #(when-not (consume-one %1 %2) [[:error]])
consume-one [] s)))
or yours:
(defn balanced? [s]
(let [tr {\( \) \[ \]}]
(empty?
(reduce-until (fn [acc v] (when (nil? (get acc 0 true)) [acc]))
#(if (= (peek %1) %2)
(pop %1)
(conj %1 (tr %2))) [] s))))
But all in all I don't find this is much a readability or
composability improvement ..., or is this ?
Regards,
--
Laurent
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---