From: sj
Subject: Creating functions with macros?
Date: 
Message-ID: <sbERc.1122$Ec3.244@newssvr22.news.prodigy.com>
I have a Lisp related computer music problem. I'm using Nyquist a
composition/synthesis extension of Xlisp and often define functions which
serve as "instruments" and then another function which is a wrapper around
the instrument.  The instrument function is responsible for generating a
single monophonic sound. The wrapper function contains boiler-plate for
multiple execution of the instrument, amplitude scaling etc...

The first few arguments to these functions are always the same but there may
be any number of optional arguments. For example a "flute" might have a
vibrato argument whereas a "marimba" would not. 

Instruments have the form:
(<name> pitch duration [:velocity][optional-arg ...])


The wrapper functions have the form:  
(<name-wrapper>  pitch-list duration [:velocity] [optional-args...])
where optional-args are passed to the instrument as key-word arguments. 

I have defined two macros but can not figure out how to deal with an
arbitrary list of optional arguments. Currently I'm using a static set of
fixed named key-word arguments. This works but passing a vibrato frequency
as "p3" is somehow less than satisfactory.


Here is an abstracted version of the code I'm currently using.
 

(defmacro definstrument (name code)
  `(defun ,name (pitch duration &key velocity p0 p1 p2  ) ,code))



(defmacro definstrument-wrapper (name inst)
  ;; Where inst is a function generated by definstrument
  `(defun ,name (pitch-list duration &key velocity p0 p1 p2)
       ( <boiler-plate>....
              (funcall ,inst (nth index pitch-list) duration 
                    :velocity velocity :p0 p0 :p1 p1 :p2 p2)
         ....)))



I would rather do something like:

(defmacro definstrument (name code &rest args)) 
;; No problem I can do this one


(defmacro definstrument-wrapper (name inst &rest args)) 
;; But not this

Thanks
-- 
Replace underscores in email address to reply

From: Barry Margolin
Subject: Re: Creating functions with macros?
Date: 
Message-ID: <barmar-ADD366.01535209082004@comcast.dca.giganews.com>
In article <··················@newssvr22.news.prodigy.com>,
 sj <··········@_swbell.net> wrote:

> Here is an abstracted version of the code I'm currently using.
>  
> 
> (defmacro definstrument (name code)
>   `(defun ,name (pitch duration &key velocity p0 p1 p2  ) ,code))
> 
> 
> 
> (defmacro definstrument-wrapper (name inst)
>   ;; Where inst is a function generated by definstrument
>   `(defun ,name (pitch-list duration &key velocity p0 p1 p2)
>        ( <boiler-plate>....
>               (funcall ,inst (nth index pitch-list) duration 
>                     :velocity velocity :p0 p0 :p1 p1 :p2 p2)
>          ....)))
> 
> 
> 
> I would rather do something like:
> 
> (defmacro definstrument (name code &rest args)) 
> ;; No problem I can do this one
> 
> 
> (defmacro definstrument-wrapper (name inst &rest args)) 
> ;; But not this
> 
> Thanks

(defmacro definstrument-wrapper (name inst &rest args)
  `(defun ,name (pitch-list duration &rest args)
      ...
      (apply ,inst (nth index pitch-list) duration args)
      ...))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: sj
Subject: Re: Creating functions with macros?
Date: 
Message-ID: <%wYRc.4468$gn7.2193@newssvr23.news.prodigy.com>
Thanks Barry for your suggestion. Unfortunately it doesn't quite solve my
problem.  The issue is that I need to pass optional arguments by keyword
and not by position. Some complex instruments may have up to a dozen
options and positional arguments become unwielding.  

I have however solved the problem by eliminating the function/wrapper
duality. I simply redefined definstrument to include the code formerly in
the wrapper. This exposes all arguments directly to both the "instrument"
and the "wrapper".



Barry Margolin wrote:

> In article <··················@newssvr22.news.prodigy.com>,
>  sj <··········@_swbell.net> wrote:
> 
>> Here is an abstracted version of the code I'm currently using.
>>  
>> 
>> (defmacro definstrument (name code)
>>   `(defun ,name (pitch duration &key velocity p0 p1 p2  ) ,code))
>> 
>> 
>> 
>> (defmacro definstrument-wrapper (name inst)
>>   ;; Where inst is a function generated by definstrument
>>   `(defun ,name (pitch-list duration &key velocity p0 p1 p2)
>>        ( <boiler-plate>....
>>               (funcall ,inst (nth index pitch-list) duration
>>                     :velocity velocity :p0 p0 :p1 p1 :p2 p2)
>>          ....)))
>> 
>> 
>> 
>> I would rather do something like:
>> 
>> (defmacro definstrument (name code &rest args))
>> ;; No problem I can do this one
>> 
>> 
>> (defmacro definstrument-wrapper (name inst &rest args))
>> ;; But not this
>> 
>> Thanks
> 
> (defmacro definstrument-wrapper (name inst &rest args)
>   `(defun ,name (pitch-list duration &rest args)
>       ...
>       (apply ,inst (nth index pitch-list) duration args)
>       ...))
> 

-- 
Replace underscores in email address to reply
From: Barry Margolin
Subject: Re: Creating functions with macros?
Date: 
Message-ID: <barmar-9A1330.08100310082004@comcast.dca.giganews.com>
In article <···················@newssvr23.news.prodigy.com>,
 sj <··········@_swbell.net> wrote:

> Thanks Barry for your suggestion. Unfortunately it doesn't quite solve my
> problem.  The issue is that I need to pass optional arguments by keyword
> and not by position. Some complex instruments may have up to a dozen
> options and positional arguments become unwielding.

My solution does that.  You pass the keyword arguments to the wrapper 
function, and it receives them in the &rest arg and passes them on to 
the instrument function.

The wrapper function won't do keyword validity checking, but that will 
happen in the instrument function.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: sj
Subject: Re: Creating functions with macros?
Date: 
Message-ID: <TfiSc.5292$Wj6.395@newssvr23.news.prodigy.com>
Yes your solution does in fact work, I most be the victim of muddle headed
thinking. Thanks again for your assistance.

Cheers
Steven Jones


Barry Margolin wrote:

> In article <···················@newssvr23.news.prodigy.com>,
>  sj <··········@_swbell.net> wrote:
> 
>> Thanks Barry for your suggestion. Unfortunately it doesn't quite solve my
>> problem.  The issue is that I need to pass optional arguments by keyword
>> and not by position. Some complex instruments may have up to a dozen
>> options and positional arguments become unwielding.
> 
> My solution does that.  You pass the keyword arguments to the wrapper
> function, and it receives them in the &rest arg and passes them on to
> the instrument function.
> 
> The wrapper function won't do keyword validity checking, but that will
> happen in the instrument function.
> 

-- 
Replace underscores in email address to reply