From: ········@gmail.com
Subject: macrology
Date: 
Message-ID: <1183544830.236482.281410@k29g2000hsd.googlegroups.com>
Hi--

I'm trying to build a macro, pat-case, which is a case for patterns.
One of the intermediate steps is to build a macro, pat-bind, which
takes a pattern, and input, and a list of forms to be executed (with
the binding variables bound to their matches for the scope in which
the forms are executed).  I'm running up against a problem with
gensyms, which I understand -- only thing is, I'm not sure how to
avoid it.

sample usage:

(pat-bind (this is a ?x and that is a ?y) (this is a lion and that is
a tiger)
     (format nil "~A ~A" ?x ?y))

Should return "LION TIGER"

Here's my code.  The problem is that the gensym matched is just a
symbol without bindings when the mapcar form is executed to compile
the let expression, so the system gives me an object-not-list error,
quite correctly.

(defmacro pat-bind (pattern input &rest forms)
  (let ((matched (gensym)))
    `(let ((,matched (pat-match ',pattern ',input)))
       (when ,matched
	 (if (eq ,matched no-bindings)
	     (progn ,@forms)
	     (let ,(mapcar (lambda (elt)
			     `(,(car elt) ,@(cdr elt))) matched)
	       ,@forms))))))

The idea is that
(pat-bind (this is a ?x and that is a ?y) (this is a lion and that is
a tiger)
     (format nil "~A ~A" ?x ?y))

Should expand to

(let ((#:G111 (pat-match (this is a ?x and that is a ?y) (this is a
lion and that is a tiger))))
  (when #:G111
    (if (eq #:G111 no-bindings)
	(progn (format nil "~A ~A" ?x ?y))
	(let ((?x 'lion)
	      (?y 'tiger))
	  (format nil "~A ~A" ?x ?y)))))

Is this a case for macrolet?

thanks,

Tiarnán

From: Alex Mizrahi
Subject: Re: macrology
Date: 
Message-ID: <468b7ab7$0$90275$14726298@news.sunsite.dk>
(message (Hello ·········@gmail.com)
(you :wrote  :on '(Wed, 04 Jul 2007 03:27:10 -0700))
(

 o> (let ((#:G111 (pat-match (this is a ?x and that is a ?y) (this is a
 o> lion and that is a tiger))))
 o>   (when #:G111
 o>     (if (eq #:G111 no-bindings)
 o>  (progn (format nil "~A ~A" ?x ?y))
 o>  (let ((?x 'lion)
 o>        (?y 'tiger))
 o>    (format nil "~A ~A" ?x ?y)))))

you're missing quotes for pat-match agruments, unless pat-match is a macro.

 o> Is this a case for macrolet?

i don't see how you can apply macrolet here.

if you want to generate LET at macroexpansion time, you need to process 
pattern list at macroexpansion time!
it's not a problem of gensym.

so, you can do something like that:

(defmacro pat-bind (pattern input &rest forms)
  (let ((matched-var (gensym))
         (marched-list (find-variables-in-pattern pattern))

and then use matched-var in generated code (as you were using matched), and 
matched-list in the MAPCAR code that is executed in macroexpansion phase.

matched-list in this example will be (list '?X '?Y)

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"scorn") 
From: Chris Russell
Subject: Re: macrology
Date: 
Message-ID: <1183557049.810780.253010@q69g2000hsb.googlegroups.com>
On Jul 4, 11:27 am, ·········@gmail.com" <········@gmail.com> wrote:
> Hi--
>
> I'm trying to build a macro, pat-case, which is a case for patterns.
> One of the intermediate steps is to build a macro, pat-bind, which
> takes a pattern, and input, and a list of forms to be executed (with
> the binding variables bound to their matches for the scope in which
> the forms are executed).  I'm running up against a problem with
> gensyms, which I understand -- only thing is, I'm not sure how to
> avoid it.
>
> sample usage:
>
> (pat-bind (this is a ?x and that is a ?y) (this is a lion and that is
> a tiger)
>      (format nil "~A ~A" ?x ?y))
>
> Should return "LION TIGER"
>
> Here's my code.  The problem is that the gensym matched is just a
> symbol without bindings when the mapcar form is executed to compile
> the let expression, so the system gives me an object-not-list error,
> quite correctly.

OK, it's time to go back to the drawing board.
With your macro that takes
(this is a ?x and that is a ?y)
(this is a lion and that is a tiger)
as literals you are not going to get much use out of the pattern
matcher. At the moment you're just describing an extremely verbose way
of saying:
(let ((?x 'lion))
      (?y 'tiger))...
which will be all fixed in place at compile time, and isn't going to
be much use to anyone.

There are two different ways you can do this; your macro can either
look like
(pat-bind ((this is a ?x and that is a ?y) input-expression) ....)
or
(pat-bind ((?x ?y) test-expression input-expression) ....)

(note the additional brackets to make things clearer)
depending on whether you want the test expression to be always known
at compile time or not.

The problem with your current code is that you know the value of
everything at compile time, but postpone a calculation you need the
result of at compile time till run time.
From: David Golden
Subject: Re: macrology
Date: 
Message-ID: <vjOii.20672$j7.378410@news.indigo.ie>
········@gmail.com wrote:

> Hi--
> 
> I'm trying to build a macro, pat-case, which is a case for patterns.
> One of the intermediate steps is to build a macro, pat-bind, which
> takes a pattern, and input, and a list of forms to be executed (with
> the binding variables bound to their matches for the scope in which
> the forms are executed).  I'm running up against a problem with
> gensyms, which I understand -- only thing is, I'm not sure how to
> avoid it.
> 

Aside: I know you may be doing this as a learning exercise rather
than as a part of some larger project, but do bear in mind that
ready-made full-blown pattern matching functionality exists in e.g.
Marco Antoniotti's  cl-unification :

http://common-lisp.net/project/cl-unification/control-flow.html
From: ········@gmail.com
Subject: Re: macrology
Date: 
Message-ID: <1183627556.330808.132510@n2g2000hse.googlegroups.com>
On Jul 4, 3:40 pm, David Golden <············@oceanfree.net> wrote:
> do bear in mind that
> ready-made full-blown pattern matching functionality exists in e.g.
> Marco Antoniotti's  cl-unification :
>
> http://common-lisp.net/project/cl-unification/control-flow.html

Thanks for this.  Looks like exactly what I need.
From: Thomas A. Russ
Subject: Re: macrology
Date: 
Message-ID: <ymiejjmpt25.fsf@sevak.isi.edu>
·········@gmail.com" <········@gmail.com> writes:

> Hi--
> 
> I'm trying to build a macro, pat-case, which is a case for patterns.
> One of the intermediate steps is to build a macro, pat-bind, which
> takes a pattern, and input, and a list of forms to be executed (with
> the binding variables bound to their matches for the scope in which
> the forms are executed).  I'm running up against a problem with
> gensyms, which I understand -- only thing is, I'm not sure how to
> avoid it.

As others have mentioned, the problem isn't with GENSYMs, but rather
with time of evaluation.  (You can check this by replacing the gensym
variable with any other fixed symbol).

> sample usage:
> 
> (pat-bind (this is a ?x and that is a ?y) (this is a lion and that is
> a tiger)
>      (format nil "~A ~A" ?x ?y))
> 
> Should return "LION TIGER"
> 
> Here's my code.  The problem is that the gensym matched is just a
> symbol without bindings when the mapcar form is executed to compile
> the let expression, so the system gives me an object-not-list error,
> quite correctly.
> 
> (defmacro pat-bind (pattern input &rest forms)
>   (let ((matched (gensym)))
>     `(let ((,matched (pat-match ',pattern ',input)))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

      This is where you generate code that will, at RUN time, produce
the bindings needed in by your pattern matcher.  In other words, the
gensym bound to "matched" will not have a value until run time.

>        (when ,matched
> 	 (if (eq ,matched no-bindings)
> 	     (progn ,@forms)
> 	     (let ,(mapcar (lambda (elt)
> 			     `(,(car elt) ,@(cdr elt))) matched)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

       This is where you need the value or "matched" at MACRO-EXPANSION
time in order to properly generate the binding form.  Unfortunately,
that value isn't produced until run time, and since run time is after
macro-expansion time, this doesn't have any hope of being correct.


> 	       ,@forms))))))

> The idea is that
> (pat-bind (this is a ?x and that is a ?y) (this is a lion and that is
> a tiger)
>      (format nil "~A ~A" ?x ?y))
> 
> Should expand to
> 
> (let ((#:G111 (pat-match (this is a ?x and that is a ?y) (this is a
> lion and that is a tiger))))
>   (when #:G111
>     (if (eq #:G111 no-bindings)
> 	(progn (format nil "~A ~A" ?x ?y))
> 	(let ((?x 'lion)
> 	      (?y 'tiger))

         ^^^^^^^^^^^^^^^^^
         But if you want the expansion to be these constants, then you
don't need to run the PAT-MATCH program anymore, since it won't produce
anything of interest.

> 	  (format nil "~A ~A" ?x ?y)))))

Now, what can be done to fix this?

You have to decide if your macro will be used with constant patterns or
not.  Since you seem to want lexical bindings of the variables, it seems
that the pattern needs to be constant.

If you can require that the patterns are defined at macro-expansion
time, then with a few modifications of your code you can make the
current structure work.  At the least, you need to be able to identify
the variables.  These modifications were suggested by Chris Russell.

So what you need to look at is an expansion more like this, where
PAT-MATCH is a function that takes a pattern and an input and produces a
binding structure or some sort.

 (let ((#:G111 (pat-match '(this is a ?x and that is a ?y) input)))
   (when #:G111
     (if (eq #:G111 *no-bindings*)
 	 (progn (format nil "~A ~A" ?x ?y))
 	 (let ((?x (get-variable-value '?x #:G111))
 	       (?y (get-variable-value '?y #:G111)))
 	  (format nil "~A ~A" ?x ?y)))))

And introduce a function GET-VARIABLE-VALUE that will lookup up and
return a binding match from whatever datastructure you use for recording
bindings in the pattern matcher.

-- 
Thomas A. Russ,  USC/Information Sciences Institute