From: joesb
Subject: Forward keyword parameter to another function
Date: 
Message-ID: <1123581728.541052.218970@g14g2000cwa.googlegroups.com>
Hi,

I have two function one calling another.
Both function take almost same keyword argument.
As a matter of fact, caller function make the call to the callee to
extends some functionality.

The question is how can I forward the keyword paramter the caller of
function 1 passed directly to function 2?

For example, let's say I have to function

(defun make-modified-car (car-type &key (color :red) (tire-size 23)
(speed 200))
   (let ((acar (make-normal-car car-type)))
        (modify-car acar :color color :tire-size tire-size :speed
speed)))

(defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
   (....))

Now the problem is that if I don't think that's the correct way.
I am force to duplicate the default value of modify-car to two places,
which is bad for maintenance.
I also can't tell, from modify-car, if the original caller actually
provide the :color, or is it just the default value.

I want to be able to do.

(defun make-modified-car (car-type &key color tire-size speed)
   (let ((acar (make-normal-car car-type)))
        (modify-car acar (passed-keyword))))  ;; only passed-in keyword
are passed through

(defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
   (....))

Is there anyway to do that?

From: M Jared Finder
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <W96dnYH1JtNIJ2XfRVn-2g@speakeasy.net>
joesb wrote:
> Hi,
> 
> I have two function one calling another.
> Both function take almost same keyword argument.
> As a matter of fact, caller function make the call to the callee to
> extends some functionality.
> 
> The question is how can I forward the keyword paramter the caller of
> function 1 passed directly to function 2?
> 
> For example, let's say I have to function
> 
> (defun make-modified-car (car-type &key (color :red) (tire-size 23)
> (speed 200))
>    (let ((acar (make-normal-car car-type)))
>         (modify-car acar :color color :tire-size tire-size :speed
> speed)))
> 
> (defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
>    (....))
> 
> Now the problem is that if I don't think that's the correct way.
> I am force to duplicate the default value of modify-car to two places,
> which is bad for maintenance.
> I also can't tell, from modify-car, if the original caller actually
> provide the :color, or is it just the default value.
> 
> I want to be able to do.
> 
> (defun make-modified-car (car-type &key color tire-size speed)
>    (let ((acar (make-normal-car car-type)))
>         (modify-car acar (passed-keyword))))  ;; only passed-in keyword
> are passed through
> 
> (defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
>    (....))
> 
> Is there anyway to do that?

Pascal already mentioned CLOS, which looks like it would have the best 
solution to this.  If you don't like that solution, you can use &rest 
and :allow-other-keys as well:

> (defun make-modified-car (car-type &key used keyword parameters &rest rest)
>   (let ((acar (make-normal-car car-type)))
>     (apply #'modify-car :allow-other-keys t rest)))
>  
> (defun modify-car (acar &key (color :red) (tire-size 23) (speed 200))
>   (....))

If you don't use any keyword parameters in make-modified-car, then you 
don't need the keywords or the allow-other-keys.

   -- MJF
From: joesb
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <1123671175.188958.232650@g43g2000cwa.googlegroups.com>
Hi,

Tried this in CLISP, doesn't work.

 (defun foo (a &key used &rest non-used)
	   (format t "~A ~A~%" used non-used))

It seems I can't use &rest after &key.

but

 (defun foo (a &rest non-used &key used)
	   (format t "~A ~A~%" used non-used))

Works fine.

I will probably have to massage the non-used list a little bit.
I'll try and see if apply #foo trick work with call-next-method though.
From: Pascal Bourguignon
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <87acjqm3iv.fsf@thalassa.informatimago.com>
"joesb" <··········@gmail.com> writes:
> Tried this in CLISP, doesn't work.
>
>  (defun foo (a &key used &rest non-used)
> 	   (format t "~A ~A~%" used non-used))
>
> It seems I can't use &rest after &key.

Yes.  CLISP is Common Lisp compliant.

> but
>
>  (defun foo (a &rest non-used &key used)
> 	   (format t "~A ~A~%" used non-used))
>
> Works fine.
>
> I will probably have to massage the non-used list a little bit.
> I'll try and see if apply #foo trick work with call-next-method though.

You should forget about # for a while.

               Always use: (function foo) to get the function named foo
                      and: (quote    foo) to get the symbol foo.
But you don't need to use: (value    foo) to get the value of foo ;-)

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

The world will now reboot.  don't bother saving your artefacts.
From: Stefan Nobis
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <877jeuyn41.fsf@snobis.de>
Pascal Bourguignon <····@mouse-potato.com> writes:

> You should forget about # for a while.

>                Always use: (function foo) to get the function named foo
>                       and: (quote    foo) to get the symbol foo.

Hmmm... why not always use #' and '?

-- 
Stefan.
From: Pascal Bourguignon
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <871x51mu0x.fsf@thalassa.informatimago.com>
Stefan Nobis <······@gmx.de> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>
>> You should forget about # for a while.
>
>>                Always use: (function foo) to get the function named foo
>>                       and: (quote    foo) to get the symbol foo.
>
> Hmmm... why not always use #' and '?

You cut too much to understand:

"joesb" <··········@gmail.com> writes:
> I will probably have to massage the non-used list a little bit.
> I'll try and see if apply #foo trick work with call-next-method though.

Because often newbies dismiss the '.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You never feed me.
Perhaps I'll sleep on your face.
That will sure show you.
From: Adam Warner
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <pan.2005.08.11.00.19.20.239371@consulting.net.nz>
On Wed, 10 Aug 2005 03:52:55 -0700, joesb wrote:
> Tried this in CLISP, doesn't work.
> 
>  (defun foo (a &key used &rest non-used)
> 	   (format t "~A ~A~%" used non-used))
> 
> It seems I can't use &rest after &key.
> 
> but
> 
>  (defun foo (a &rest non-used &key used)
> 	   (format t "~A ~A~%" used non-used))
> 
> Works fine.

(defun foo (&key (key1 :key1-default key1-used?)
                 (key2 :key2-default key2-used?))
  (format t "~S ~S ~S ~S~%" key1 key1-used? key2 key2-used?))

[9]> (foo)
:KEY1-DEFAULT NIL :KEY2-DEFAULT NIL
NIL
[10]> (foo :key2 123)
:KEY1-DEFAULT NIL 123 T
NIL

You can portably check whether a key has been supplied in ANSI Common
Lisp:

3.4 Lambda Lists
<http://www.lispworks.com/documentation/HyperSpec/Body/03_d.htm>

3.4.1 Ordinary Lambda Lists
<http://www.lispworks.com/documentation/HyperSpec/Body/03_da.htm>

({var | (keyword-name var)} [init-form [supplied-p-parameter]])
i.e. 
( key1                      :key1-default          key1-used? )

Regards,
Adam
From: Peder O. Klingenberg
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <ks7jevo1r0.fsf@beto.netfonds.no>
"joesb" <··········@gmail.com> writes:

> (defun make-modified-car (car-type &key color tire-size speed)
>    (let ((acar (make-normal-car car-type)))
>         (modify-car acar (passed-keyword))))  ;; only passed-in keyword
> are passed through
>
> (defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
>    (....))
>
> Is there anyway to do that?

Perhaps you can combine &rest and &key in make-modified-car?

(defun make-modified-car (car-type &rest keywords &key color tire-size speed)
  (let* ((acar (make-normal-car car-type)))
         (apply modify-car acar keywords))
    ;;presumably use color tire-size and speed here as well.
    acar)

...Peder...
-- 
I wish a new life awaited _me_ in some off-world colony.
From: Pascal Costanza
Subject: Re: Forward keyword parameter to another function
Date: 
Message-ID: <3lrep6F142p5mU1@individual.net>
joesb wrote:
> Hi,
> 
> I have two function one calling another.
> Both function take almost same keyword argument.
> As a matter of fact, caller function make the call to the callee to
> extends some functionality.
> 
> The question is how can I forward the keyword paramter the caller of
> function 1 passed directly to function 2?
> 
> For example, let's say I have to function
> 
> (defun make-modified-car (car-type &key (color :red) (tire-size 23)
> (speed 200))
>    (let ((acar (make-normal-car car-type)))
>         (modify-car acar :color color :tire-size tire-size :speed
> speed)))
> 
> (defun modify-car (acar &key (color :red) (tire-size 23) (speed 200)
>    (....))

Can you reformulate the solution like this?

(defun make-modified-car (car-type &key (color :red) (tire-size 23) 
(speed 200))
   (make-normal-car car-type :color color :tire-size tire-size :speed 
speed))

Or even use inheritance?

(defclass modified-car (normal-car)
   ()
   (:default-initargs :color :red :tire-size 23 :speed 200))


Pascal

-- 
In computer science, we stand on each other's feet. - Brian K. Reid