From: Tamas K Papp
Subject: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <75785eF16sse2U1@mid.individual.net>
I was writing a program where I am calculating various functions of
the same two parameters, these functions are best defined
sequentially.  I got tired of typing the same arguments many times
(when they call previous functions), so I implemented a macro:

(defmacro with-parametrized-formulas ((&rest parameters)
				      (&rest name-body-pairs)
				      &body body)
  "Sequentially define (function-name (parameters) body) functions,
and have the a symbol-macro name expand to (function-name parameters).
Function-name is a fresh symbol.  Example:

  (with-parametrized-formulas (a b)
    ((f (+ a b))
     (g (+ f (* a b))))
    (g 3 7)) ; => 31 (which is 3+7+3*7)"
  (assert (and (every #'symbolp parameters)
	       (every (lambda (name-body-pair)
			(symbolp (car name-body-pair))) name-body-pairs)))
  (labels ((rec (name-body-pairs)
	     (let* ((name (first (car name-body-pairs)))
		    (function-body (second (car name-body-pairs)))
		    (rest (cdr name-body-pairs)))
	       `(flet ((,function-name (,@parameters)
			 ,function-body))
		  (symbol-macrolet ((,name (,function-name ,@parameters)))
		    ,@(if rest
			  (list (rec rest)) ; ugly? workaround?
			  body))))))
    (rec name-body-pairs)))

which saved me a lot of pain.  BTW, is the final splicing of the body
bad style?  I wrap rec in a list, so that the body can be spliced
neatly, suggestions for a more idiomatic style are appreciated.

(with-parametrized-formulas (a b)
    ((f (+ a b))
     (g (+ f (* a b))))
    (g 3 7))

expands to

(FLET ((F (A B)
         (+ A B)))
  (SYMBOL-MACROLET ((F (F A B)))
    (FLET ((G (A B)
             (+ F (* A B))))
      (SYMBOL-MACROLET ((G (G A B)))
        (G 3 7)))))

This macro saved me so much typing and useless duplication (I am not
going to post examples since I don't think anyone is interested, but
most of the calculations had 10-15 steps).  I just love Lisp.

Tamas

From: Thomas A. Russ
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <ymiab69mqv6.fsf@blackcat.isi.edu>
Tamas K Papp <······@gmail.com> writes:
 > (defmacro with-parametrized-formulas ((&rest parameters)
 > 				      (&rest name-body-pairs)
 > 				      &body body)
 >   "Sequentially define (function-name (parameters) body) functions,
 > and have the a symbol-macro name expand to (function-name parameters).
 > Function-name is a fresh symbol.  Example:
 > 
 >   (with-parametrized-formulas (a b)
 >     ((f (+ a b))
 >      (g (+ f (* a b))))
 >     (g 3 7)) ; => 31 (which is 3+7+3*7)"
 >   (assert (and (every #'symbolp parameters)
 > 	       (every (lambda (name-body-pair)
 > 			(symbolp (car name-body-pair))) name-body-pairs)))
 >   (labels ((rec (name-body-pairs)
 > 	     (let* ((name (first (car name-body-pairs)))
 > 		    (function-body (second (car name-body-pairs)))
 > 		    (rest (cdr name-body-pairs)))
 > 	       `(flet ((,function-name (,@parameters)
 > 			 ,function-body))
 > 		  (symbol-macrolet ((,name (,function-name ,@parameters)))
 > 		    ,@(if rest
 > 			  (list (rec rest)) ; ugly? workaround?
 > 			  body))))))
 >     (rec name-body-pairs)))
> 
> which saved me a lot of pain.  BTW, is the final splicing of the body
> bad style?  I wrap rec in a list, so that the body can be spliced
> neatly, suggestions for a more idiomatic style are appreciated.

I don't think so.  Normally body ends up being spliced into most macros
that way.

I do note that in the code above, you won't splice body it at all if
REST is non-NIL.  Is that what you intended to do?  Oh, wait, I guess it
ends up getting recursively expanded, so it will eventually end up in
the lowest level.

I suppose that's a clever way to do this.  But I would tend to pass body
as a parameter to the expansion function.  It's less clever, but I think
it's a bit clearer.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: namekuseijin
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <gsme2n$pc5$1@adenine.netfront.net>
Tamas K Papp wrote:
> I was writing a program where I am calculating various functions of
> the same two parameters, these functions are best defined
> sequentially.  I got tired of typing the same arguments many times
> (when they call previous functions), so I implemented a macro:

> (with-parametrized-formulas (a b)
>     ((f (+ a b))
>      (g (+ f (* a b))))
>     (g 3 7))

err... how about:

(let* ((a 3)(b 7) ; parameters
        ; formulas...
        (f (+ a b))
        (g (+ f (* a b))))
   g)

Plus, let* is shorter. :)

> expands to
> 
> (FLET ((F (A B)
>          (+ A B)))
>   (SYMBOL-MACROLET ((F (F A B)))
>     (FLET ((G (A B)
>              (+ F (* A B))))
>       (SYMBOL-MACROLET ((G (G A B)))
>         (G 3 7)))))

boy, CL is butt ugly... :P
From: Tamas K Papp
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <758k6rF174ho6U1@mid.individual.net>
On Wed, 22 Apr 2009 03:49:57 -0300, namekuseijin wrote:

> Tamas K Papp wrote:
>> I was writing a program where I am calculating various functions of the
>> same two parameters, these functions are best defined sequentially.  I
>> got tired of typing the same arguments many times (when they call
>> previous functions), so I implemented a macro:
> 
>> (with-parametrized-formulas (a b)
>>     ((f (+ a b))
>>      (g (+ f (* a b))))
>>     (g 3 7))
> 
> err... how about:
> 
> (let* ((a 3)(b 7) ; parameters
>         ; formulas...
>         (f (+ a b))
>         (g (+ f (* a b))))
>    g)
> 
> Plus, let* is shorter. :)

That was just an example to demonstrate the macro.  In the context of
my code, I wanted to end up with 7-10 _functions_ in 2 parameters
which I explored, both numerically and graphically.

>> expands to
>> 
>> (FLET ((F (A B)
>>          (+ A B)))
>>   (SYMBOL-MACROLET ((F (F A B)))
>>     (FLET ((G (A B)
>>              (+ F (* A B))))
>>       (SYMBOL-MACROLET ((G (G A B)))
>>         (G 3 7)))))
> 
> boy, CL is butt ugly... :P

:-)

Tamas
From: namekuseijin
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <gsneua$26ni$1@adenine.netfront.net>
Tamas K Papp escreveu:
> On Wed, 22 Apr 2009 03:49:57 -0300, namekuseijin wrote:
> 
>> Tamas K Papp wrote:
>>> I was writing a program where I am calculating various functions of the
>>> same two parameters, these functions are best defined sequentially.  I
>>> got tired of typing the same arguments many times (when they call
>>> previous functions), so I implemented a macro:
>>> (with-parametrized-formulas (a b)
>>>     ((f (+ a b))
>>>      (g (+ f (* a b))))
>>>     (g 3 7))
>> err... how about:
>>
>> (let* ((a 3)(b 7) ; parameters
>>         ; formulas...
>>         (f (+ a b))
>>         (g (+ f (* a b))))
>>    g)
>>
>> Plus, let* is shorter. :)
> 
> That was just an example to demonstrate the macro.  In the context of
> my code, I wanted to end up with 7-10 _functions_ in 2 parameters
> which I explored, both numerically and graphically.

But the point is that I think you just reimplemented let*. ;)

-- 
a game sig: http://tinyurl.com/d3rxz9
From: Barry Margolin
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <barmar-D05194.21291922042009@mara100-84.onlink.net>
In article <·············@adenine.netfront.net>,
 namekuseijin <············@gmail.com> wrote:

> Tamas K Papp escreveu:
> > On Wed, 22 Apr 2009 03:49:57 -0300, namekuseijin wrote:
> > 
> >> Tamas K Papp wrote:
> >>> I was writing a program where I am calculating various functions of the
> >>> same two parameters, these functions are best defined sequentially.  I
> >>> got tired of typing the same arguments many times (when they call
> >>> previous functions), so I implemented a macro:
> >>> (with-parametrized-formulas (a b)
> >>>     ((f (+ a b))
> >>>      (g (+ f (* a b))))
> >>>     (g 3 7))
> >> err... how about:
> >>
> >> (let* ((a 3)(b 7) ; parameters
> >>         ; formulas...
> >>         (f (+ a b))
> >>         (g (+ f (* a b))))
> >>    g)
> >>
> >> Plus, let* is shorter. :)
> > 
> > That was just an example to demonstrate the macro.  In the context of
> > my code, I wanted to end up with 7-10 _functions_ in 2 parameters
> > which I explored, both numerically and graphically.
> 
> But the point is that I think you just reimplemented let*. ;)

Not if he uses G multiple times with different arguments:

(with-parametrized-formulas (a b)
    ((f (+ a b))
     (g (+ f (* a b))))
  (list (g 1 2) (g 3 4)))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Tamas K Papp
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <75a2mbF16s1fcU1@mid.individual.net>
On Wed, 22 Apr 2009 21:29:19 -0400, Barry Margolin wrote:

> In article <·············@adenine.netfront.net>,
>  namekuseijin <············@gmail.com> wrote:
> 
>> Tamas K Papp escreveu:
>> > On Wed, 22 Apr 2009 03:49:57 -0300, namekuseijin wrote:
>> > 
>> >> Tamas K Papp wrote:
>> >>> I was writing a program where I am calculating various functions of
>> >>> the same two parameters, these functions are best defined
>> >>> sequentially.  I got tired of typing the same arguments many times
>> >>> (when they call previous functions), so I implemented a macro:
>> >>> (with-parametrized-formulas (a b)
>> >>>     ((f (+ a b))
>> >>>      (g (+ f (* a b))))
>> >>>     (g 3 7))
>> >> err... how about:
>> >>
>> >> (let* ((a 3)(b 7) ; parameters
>> >>         ; formulas...
>> >>         (f (+ a b))
>> >>         (g (+ f (* a b))))
>> >>    g)
>> >>
>> >> Plus, let* is shorter. :)
>> > 
>> > That was just an example to demonstrate the macro.  In the context of
>> > my code, I wanted to end up with 7-10 _functions_ in 2 parameters
>> > which I explored, both numerically and graphically.
>> 
>> But the point is that I think you just reimplemented let*. ;)
> 
> Not if he uses G multiple times with different arguments:
> 
> (with-parametrized-formulas (a b)
>     ((f (+ a b))
>      (g (+ f (* a b))))
>   (list (g 1 2) (g 3 4)))

I am glad that Thomas and Barry got it :-) In fact, this was a
comparatively simple calculation at the end of a function:

(with-parametrized-formulas (mu rho)
  ;; pasted from Maxima
  ((beta (/ (+ (* (+ (* LF MU) (- 1)) RHO) (- (* LF MU)) 1)
            (+ (* (+ (* -1 LF) LW) MU) (* (+ 1 LF) MU RHO))))
   (q (/ (+ (* (+ (* LF MU) LF) RHO) (* LF LW MU) (- LF))
           (+ (* -1 LF) LW (* (+ 1 LF) RHO))))
   (b (- (/ (* (+ (* LF (+ LW 1) MU) (- LW) (- 1)) RHO)
              (+ (* -1 LF) LW (* (+ 1 LF) RHO)))))
   ;; elasticities, other statistics
   (denom (- (+ (* alpha mu) 1) b q))
   (pQnumerator (- (* (- 1 alpha) (- 1 b)) q))
   (etapQ (/ (* (- mu) pQnumerator) denom))
   (etathetaQ (/ (- (- (+ mu 1) b)) denom))
   (etaratio  (/ etathetaQ etapQ))
   (wage (- (+ (* beta mu) 1) q))
   (replacement-ratio (/ b wage))
   (labor-share (/ wage (+ mu 1))))
  (list #'beta #'q #'b #'etapQ 
        #'etathetaQ #'etaratio #'labor-share #'denom))

Then I save the returned functions and explore them, which meant
making pretty graphs of these functions and eyeballing them, and then
later trying to match them to moments in the data.  (I was calibrating
a simple economic model of the labor market).  It would be a huge mess
without this macro, I would have to spell out the parameters all the
time.  And no, I don't see how let* would help me :-) So again, Lisp
rocks.

Tamas
From: namekuseijin
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <gsoqn9$1mhe$1@adenine.netfront.net>
Tamas K Papp wrote:
> Then I save the returned functions and explore them, which meant
> making pretty graphs of these functions and eyeballing them, and then
> later trying to match them to moments in the data.  (I was calibrating
> a simple economic model of the labor market).  It would be a huge mess
> without this macro, I would have to spell out the parameters all the
> time.  And no, I don't see how let* would help me :-) So again, Lisp
> rocks.

You want the intermediary functions, not just the results, I see.  Yes, 
very useful.

I got confused when you wrote things like:

(etathetaQ (/ (- (- (+ mu 1) b)) denom))

Where denom is used like a value, but should actually be a function call 
in following formulae.  I noticed the intermediary step making denom a 
macro standing for (denom mu rho)...
From: Mirko
Subject: Re: with-parametrized-formulas (macro style question)
Date: 
Message-ID: <c771436d-20bd-4523-889f-ec08a1c7841d@o30g2000vbc.googlegroups.com>
On Apr 22, 10:39 pm, Tamas K Papp <······@gmail.com> wrote:
> On Wed, 22 Apr 2009 21:29:19 -0400, Barry Margolin wrote:
> > In article <·············@adenine.netfront.net>,
> >  namekuseijin <············@gmail.com> wrote:
>
> >> Tamas K Papp escreveu:
> >> > On Wed, 22 Apr 2009 03:49:57 -0300, namekuseijin wrote:
>
> >> >> Tamas K Papp wrote:
> >> >>> I was writing a program where I am calculating various functions of
> >> >>> the same two parameters, these functions are best defined
> >> >>> sequentially.  I got tired of typing the same arguments many times
> >> >>> (when they call previous functions), so I implemented a macro:
> >> >>> (with-parametrized-formulas (a b)
> >> >>>     ((f (+ a b))
> >> >>>      (g (+ f (* a b))))
> >> >>>     (g 3 7))
> >> >> err... how about:
>
> >> >> (let* ((a 3)(b 7) ; parameters
> >> >>         ; formulas...
> >> >>         (f (+ a b))
> >> >>         (g (+ f (* a b))))
> >> >>    g)
>
> >> >> Plus, let* is shorter. :)
>
> >> > That was just an example to demonstrate the macro.  In the context of
> >> > my code, I wanted to end up with 7-10 _functions_ in 2 parameters
> >> > which I explored, both numerically and graphically.
>
> >> But the point is that I think you just reimplemented let*. ;)
>
> > Not if he uses G multiple times with different arguments:
>
> > (with-parametrized-formulas (a b)
> >     ((f (+ a b))
> >      (g (+ f (* a b))))
> >   (list (g 1 2) (g 3 4)))
>
> I am glad that Thomas and Barry got it :-) In fact, this was a
> comparatively simple calculation at the end of a function:
>

I keep getting it, and then ungetting it :-(  One thing is sure.  I'm
getting old.

Mirko