Here is the match-forms function:

(defn match-forms [p s]
  (if (= '_ p) []
      (loop [p p s s vars []]
        (cond (and (= 0 (count p)) (= 0 (count s))) vars
              (= 0 (count s)) false
              true
              (let [fp (first p) rp (rest p)
                    fs (first s) rs (rest s)]
                (cond
                 ;; wildcard pattern
                 (= '_ fp) (recur rp rs vars)
                 ;; rest
                 (and (symbol? fp) (= '& fp))
                 (conj (conj vars (first rp)) `'~(conj rs fs))
                 ;; add variable to bindings
                 (symbol? fp) (recur rp rs (conj (conj vars fp)
`'~fs))
                 ;; match a symbol
                 (and (seq? fp) (= 'quote (first fp)))
                 (if (= fs (second fp)) (recur rp rs vars) false)
                 ;; not matching
                 true false))))))

It basically only add a wildcard token to the pattern matching
algorithm, but it is less general too because it only support simple
list.

Here's how I intend to use it:

(defn- expand-parser-body [body s]
  (let [r (gensym 'r)]
    (match body
           (_ '<- _) (parser-error)
           (p) (list p s)
           (v '<- p & xs)
           `(let [~r (~p ~s)]
              (if (= 0 (count ~r)) ~r
                  ~(expand-parser-body xs)))
           (p & xs)
           `(let [~r (~p ~s)]
              (if (= 0 (count ~r)) ~r
                  ~(expand-parser-body xs))))))

(defmacro parser [& body]
  (let [s (gensym 's)]
    `(fn [~s] ~(expand-parser-body body s))))

It's for a small parser combinator library I'm writing.


On Aug 24, 1:26 pm, Chouser <[EMAIL PROTECTED]> wrote:
> On Sun, Aug 24, 2008 at 12:46 PM, budu <[EMAIL PROTECTED]> wrote:
>
> > Hi, I've been having a great time using Clojure in the last few month.
> > But this week I've come accross something that is blocking me. I'm
> > trying to write a very simple pattern matching macro to use in other
> > macros for matching forms. I've based my macro on one posted in this
> > group by James Reeves a few months ago. It's working great but, as it
> > uses eval, it does not evaluate in the lexical scope.
>
> > (defmacro match [value & clauses]
> >  (when (and clauses (= 0 (rem (count clauses) 2)))
> >    (let [m (gensym 'm)]
> >      `(if-let ~m (match-forms '~(first clauses) ~value)
> >         (eval (list 'let ~m '~(second clauses)))
> >         (match ~value ~@(rrest clauses))))))
>
> > user=> (match '(1 2 3) (a b c) (list c b a))
> > (3 2 1)
>
> I believe you're referring to 
> this:http://groups.google.com/group/clojure/browse_thread/thread/c6db91161...
>
> However, you've made some changes -- your match macro above is
> different from James Reeves', and simply renaming "matches?" to
> "match-forms" still doesn't allow your example to work.  This makes it
> difficult to help you!  Would you mind posting a working example?
>
> So it's hard to be sure, but I suspect we'll be able to find a
> solution.  I think this because the eval in match is executed at
> runtime, not when the macro is evaluated.  This means I think we ought
> to be able to make the match macro emit the appropriate code to have
> the same behavior as the eval, but without any eval at all.
>
> --Chouser
--~--~---------~--~----~------------~-------~--~----~
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
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to