The easiest way would be to factor out the bracket matching code, since
that's the only thing that changes between your different case statements.
For instance:

  (defn valid-parens? [s]
    (let [opening-brackets {\( \), \[ \], \{ \}}
          closing-brackets (clojure.set/map-invert opening-brackets)]
      (loop [cs (seq s), stack []]
        (if-not cs
          (empty? stack)
          (let [c (first cs), cs (next cs)]
            (if (opening-brackets c)
              (recur cs (conj stack c))
              (if-let [b (closing-brackets c)]
                (if (= (peek stack) b)
                  (recur cs (pop stack))
                  false)
                (recur cs stack)))))))

Another way you could do it is to replace your recursive call with a
continuation.

- James

On 26 June 2016 at 13:43, Botond Balázs <balazsbot...@gmail.com> wrote:

> Hi,
>
> Here is my solution to 4clojure problem #177:
>
> Write a function that takes in a string and returns truthy if all square [
>> ] round ( ) and curly { } brackets are properly paired and legally nested,
>> or returns falsey otherwise.
>>
>
> (defn valid-parens?
>   [s]
>   (loop [[ch & chs] s stack []]
>     (if (nil? ch)
>       (empty? stack)
>       (case ch
>         (\( \[ \{) (recur chs (conj stack ch))
>         \) (if (= (peek stack) \()
>              (recur chs (pop stack))
>              false)
>         \] (if (= (peek stack) \[)
>              (recur chs (pop stack))
>              false)
>         \} (if (= (peek stack) \{)
>              (recur chs (pop stack))
>              false)
>         (recur chs stack)))))
>
> This works but I don't like the repetition in the case branches. But the
> repeated code contains a recur call so I can't simply refactor it into a
> helper function. How can I achieves something like the following, but
> without consuming the stack?
>
> (defn valid-parens?
>   ([s]
>    (valid-parens? s []))
>   ([[ch & chs] stack]
>    (if (nil? ch)
>      (empty? stack)
>      (letfn [(match? [p]
>                (if (= (peek stack) p)
>                  (valid-parens? chs (pop stack))
>                  false))]
>        (case ch
>          (\( \[ \{) (valid-parens? chs (conj stack ch))
>          \) (match? \()
>          \] (match? \[)
>          \} (match? \{)
>          (valid-parens? chs stack))))))
>
> Thanks!
> Botond
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to