From: Jeff
Subject: Pattern macro definition help
Date: 
Message-ID: <K2n3d.467737$%_6.206865@attbi_s01>
I've been trying to define a macro that will solve the following
problem: given a list of items, return true if the items in question
meet the criteria of pattern macro being defined. For example, the
following would be a sample pattern:

(defpattern fold-constant-add
  ((numberp ?)
   (numberp ?)
   (eq ? '+))
  (+ ? ?))

Where '?' is defined as the next car in the list. So, an example of how
this pattern would work would be:

(fold-constant-add '(1 2 + 4 5)) ==> (3 4 5)

The problem itself is rather simple, but I'm having difficuly
determining how to swap the ? (or any other symbol) with the next car
in the list... ignoring gensyms for simplicity:

(defmacro defpattern name ((&rest matches) returns)
  `(setf ,name (lambda (list)
                 (labels ((matches (list to-list)
                            (if (null to-list)
                                (eval ,returns)
                              (when (eval (car to-list))
                                (matches (cdr list) (cdr to-list))))))
                   (matches list ,matches)))))

Well, even though the above is crap, I hope it shows the general idea
of what I would like to have done. The difficulties are in the (eval
(car to-list)) -- I need to insert the current car in 'list' somehow --
and in the return eval; same problem.

Any suggestions on how something like this might be done is
appreciated. Thanks in advance.

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)

From: Pascal Bourguignon
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <87k6uplx4q.fsf@thalassa.informatimago.com>
"Jeff" <···@nospam.insightbb.com> writes:
> (defpattern fold-constant-add
>   ((numberp ?)
>    (numberp ?)
>    (eq ? '+))
>   (+ ? ?))
> 
> The problem itself is rather simple, but I'm having difficuly
> determining how to swap the ? (or any other symbol) with the next car
> in the list... ignoring gensyms for simplicity:

First, use a function and quote arguments:

(make-pattern 'fold-constant-add
   '((numberp ?)
     (numberp ?)
     (eq ? '+))
   '(+ ? ?))

Once you've implemented the make-pattern function you can trivially
implement a macro with it:

   (defmacro defpattern (name pattern substitution)
      `(make-pattern ',name ',pattern ',substitution))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Christophe Turle
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <cim6jh$u8k$1@amma.irisa.fr>
Jeff wrote:
> I've been trying to define a macro that will solve the following
> problem: given a list of items, return true if the items in question
> meet the criteria of pattern macro being defined. For example, the
> following would be a sample pattern:
> 
> (defpattern fold-constant-add
>   ((numberp ?)
>    (numberp ?)
>    (eq ? '+))
>   (+ ? ?))
> 
> Where '?' is defined as the next car in the list. So, an example of how
> this pattern would work would be:
> 
> (fold-constant-add '(1 2 + 4 5)) ==> (3 4 5)
> 

i propose this :

(defpattern fold-constant-add ((? a :pred numberp) (? b :pred numberp) + (? rest :card :0-*))
  `(,(+ ?a ?b) ,@?rest) )

sort of extended macro producing a function with a different lambda-destructuring.


Christophe Turle.









> The problem itself is rather simple, but I'm having difficuly
> determining how to swap the ? (or any other symbol) with the next car
> in the list... ignoring gensyms for simplicity:
> 
> (defmacro defpattern name ((&rest matches) returns)
>   `(setf ,name (lambda (list)
>                  (labels ((matches (list to-list)
>                             (if (null to-list)
>                                 (eval ,returns)
>                               (when (eval (car to-list))
>                                 (matches (cdr list) (cdr to-list))))))
>                    (matches list ,matches)))))
> 
> Well, even though the above is crap, I hope it shows the general idea
> of what I would like to have done. The difficulties are in the (eval
> (car to-list)) -- I need to insert the current car in 'list' somehow --
> and in the return eval; same problem.
> 
> Any suggestions on how something like this might be done is
> appreciated. Thanks in advance.
> 
> Jeff
> 
From: Wade Humeniuk
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <L3D3d.29634$yW6.6733@clgrps12>
Jeff wrote:

> I've been trying to define a macro that will solve the following
> problem: given a list of items, return true if the items in question
> meet the criteria of pattern macro being defined. For example, the
> following would be a sample pattern:
> 
> (defpattern fold-constant-add
>   ((numberp ?)
>    (numberp ?)
>    (eq ? '+))
>   (+ ? ?))
> 
> Where '?' is defined as the next car in the list. So, an example of how
> this pattern would work would be:
> 
> (fold-constant-add '(1 2 + 4 5)) ==> (3 4 5)
> 
> The problem itself is rather simple, but I'm having difficuly
> determining how to swap the ? (or any other symbol) with the next car
> in the list... ignoring gensyms for simplicity:\

Try this on.  Not sure what you want to return if the pattern
does not match (This macro just returns the original list
if the pattern does not match.

(defmacro defpattern (name assertion &body body)
   (let ((head (make-symbol "HEAD-"))
         (tail (make-symbol "TAIL-")))
     `(defun ,name (list)
        (let ((,head list))
          (symbol-macrolet ((? (pop ,head)))
            (if (and ,@assertion)
                (let ((,tail ,head))
                  (setf ,head list)
                  (cons (progn ,@body) ,tail))
              list))))))

CL-USER 5 > (fold-constant-add '(1 2 + 4 5))
(3 4 5)

CL-USER 6 >

Wade
From: Steven E. Harris
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <jk46568r0g0.fsf@W003275.na.alarismed.com>
Wade Humeniuk <····································@telus.net> writes:

> CL-USER 5 > (fold-constant-add '(1 2 + 4 5))
> (3 4 5)

Not knowing exactly what the OP intended, it's a shame that

  (fold-constant-add '(1 2 3 + 4 5))

does not produce

  (1 5 4 5)

respecting any three element number-number-+ subsequence. But then
we're wandering into writing a Forth interpreter.

-- 
Steven E. Harris
From: Jeff
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <Yi24d.22511$wV.21654@attbi_s54>
Steven E. Harris wrote:

> Wade Humeniuk <····································@telus.net> writes:
> 
> > CL-USER 5 > (fold-constant-add '(1 2 + 4 5))
> > (3 4 5)
> 
> Not knowing exactly what the OP intended, it's a shame that
> 
>   (fold-constant-add '(1 2 3 + 4 5))
> 
> does not produce
> 
>   (1 5 4 5)
> 
> respecting any three element number-number-+ subsequence. But then
> we're wandering into writing a Forth interpreter.

Very astute :)

This is actually just a very simplistic stack intermediate language for
a compiler I've written. I'm just going through the optimization phase
and handling some simple constant folding. Your above "problem"
wouldn't happen and could be handled just fine. For example:

(fold-constant-add '(1 2 3 + + 3 4)) =>
(fold-constant-add '(1 5 + 3 4)) =>
(fold-constant-add '(6 3 4)) =>
(6 3 4)

fold-constant-add, of course, isn't the only optimization. Simple
DUP/DROP pairs being optimized to a NOP and other similar optimizations
for what assembly code will be generated (like SWAP -).

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)
From: Steven E. Harris
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <83brfz9jo1.fsf@torus.sehlabs.com>
"Jeff" <···@nospam.insightbb.com> writes:

> Your above "problem" wouldn't happen and could be handled just
> fine. For example:
>
> (fold-constant-add '(1 2 3 + + 3 4)) =>
> (fold-constant-add '(1 5 + 3 4)) =>

I was commenting that Wade's very nice solution could not do this
reduction. It only catches the "number, number, +" sequence at the
start of the input sequence (or stack).

,----
| CL-USER> (fold-constant-add '(1 2 + 4 5))
| (3 4 5)
| CL-USER> (fold-constant-add '(1 2 3 + 4 5))
| (1 2 3 + 4 5)
`----

I agree that it /could/ be handled just fine; Wade's implementation
would need some adjustment to walk the sequence looking for candidate
subsequences rather than just trying from the start and giving up if
the match fails.

Could you clarify what you meant by the "problem wouldn't happen"? I'm
not sure we understood one another.

-- 
Steven E. Harris
From: Jeff
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <Kb64d.23669$wV.17940@attbi_s54>
Steven E. Harris wrote:

> Could you clarify what you meant by the "problem wouldn't happen"? I'm
> not sure we understood one another.

I just meant to imply that the method by which the incoming list of
data is created is very controlled and completely internal. If by some
chance that an error in the data /could/ be introduced, it would have
been captured long before getting to the optimization phase and would
have been reported.

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)
From: Jeff
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <yj24d.22513$wV.19543@attbi_s54>
Steven E. Harris wrote:

> But then
> we're wandering into writing a Forth interpreter.

I should also note that I've already implemented this in Forth just
fine, just trying Lisp on for size ;)

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)
From: Steven E. Harris
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <8365679jbo.fsf@torus.sehlabs.com>
"Jeff" <···@nospam.insightbb.com> writes:

> I should also note that I've already implemented this in Forth just
> fine, just trying Lisp on for size ;)

Funny, I just started studying Forth a few weeks ago to try it on for
size. I was intrigued by the familiarity: The programs I wrote for my
HP calculators about 15 years ago, or at least that same mode of
thinking, suddenly seemed both portable and relevant to a new context.

-- 
Steven E. Harris
From: Jeff
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <Jg64d.23696$wV.16349@attbi_s54>
Steven E. Harris wrote:

> "Jeff" <···@nospam.insightbb.com> writes:
> 
> > I should also note that I've already implemented this in Forth just
> > fine, just trying Lisp on for size ;)
> 
> Funny, I just started studying Forth a few weeks ago to try it on for
> size. I was intrigued by the familiarity: The programs I wrote for my
> HP calculators about 15 years ago, or at least that same mode of
> thinking, suddenly seemed both portable and relevant to a new context.

Forth is a beautiful language. The two best features of Forth and Lisp
are what it does for the programmer that I have yet to see duplicated
by any other language (except perhaps Haskell):

1. It forces you to think differently -- always good.
2. It encourages *complete* use of the language to solve problems.

By #2 I mean to say the reader/parser, compiler, macros/DOES> and
everything else. These two features alone contribute to the statement
"Forth is a programmer amplifier" (later repeated about Lisp by Martin
Rodgers). Definitely true for both languages.

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)
From: Rahul Jain
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <87isa1x6y1.fsf@nyct.net>
"Jeff" <···@nospam.insightbb.com> writes:

> 1. It forces you to think differently -- always good.

Lisp forces you to think the way you want to, actually. Yes, that is
different from the way other languages force you to think, but not sure
that's what you meant.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Jeff
Subject: Re: Pattern macro definition help
Date: 
Message-ID: <NdJ3d.127789$3l3.62223@attbi_s03>
Wade Humeniuk wrote:

> 
> (defmacro defpattern (name assertion &body body)
>    (let ((head (make-symbol "HEAD-"))
>          (tail (make-symbol "TAIL-")))
>      `(defun ,name (list)
>         (let ((,head list))
>           (symbol-macrolet ((? (pop ,head)))
>             (if (and ,@assertion)
>                 (let ((,tail ,head))
>                   (setf ,head list)
>                   (cons (progn ,@body) ,tail))
>               list))))))

What can I say other than "awesome!" I ended up trying to go another
route (which was effective), but this is just fantastic. Thank you very
much! And yes, if the pattern didn't match, the original list is what I
wanted returned.

Jeff

-- 
Progress in computer technology is waiting for people to stop
re-inventing the wheel.
 - Dr. William Bland (comp.lang.lisp)