Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function arguments

0 views
Skip to first unread message

Bob Felts

unread,
Apr 18, 2006, 5:14:40 PM4/18/06
to
Is there any way to write a function so that it can be called either as:

(foo 1 2 3)

or
(foo '(1 2 3))

such that 1 is bound, say, to x, 2 to y, and 3 to z?

--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth

Rainer Joswig

unread,
Apr 18, 2006, 5:41:14 PM4/18/06
to
Am 18.04.2006 23:14 Uhr schrieb "Bob Felts" unter <wr...@stablecross.com> in
1he02hi.teqmou8dwdq8N%wr...@stablecross.com:

> Is there any way to write a function so that it can be called either as:
>
> (foo 1 2 3)
>
> or
> (foo '(1 2 3))
>
> such that 1 is bound, say, to x, 2 to y, and 3 to z?

For example like this:

(defun foo (&optional x y z)
(if (listp x)
(apply #'foo x)
(+ x y z)))

CL-USER 11 > (foo 1 2 3)
6

CL-USER 12 > (foo '(1 2 3))
6

Peter Seibel

unread,
Apr 18, 2006, 5:42:28 PM4/18/06
to
wr...@stablecross.com (Bob Felts) writes:

> Is there any way to write a function so that it can be called either as:
>
> (foo 1 2 3)
>
> or
> (foo '(1 2 3))

It's seems unlikely to me that this is a good idea, but if you really
want to:

(defun foo (a &optional b c)
(flet ((work (a b c) ...))
(if (consp a) (apply #'work a) (work a b c))))

-Peter

--
Peter Seibel * pe...@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/

Bob Felts

unread,
Apr 18, 2006, 7:46:50 PM4/18/06
to
Peter Seibel <pe...@gigamonkeys.com> wrote:

> wr...@stablecross.com (Bob Felts) writes:
>
> > Is there any way to write a function so that it can be called either as:
> >
> > (foo 1 2 3)
> >
> > or
> > (foo '(1 2 3))
>
> It's seems unlikely to me that this is a good idea, but if you really
> want to:
>
> (defun foo (a &optional b c)
> (flet ((work (a b c) ...))
> (if (consp a) (apply #'work a) (work a b c))))
>

There's a method to my madness. Suppose I have two functions, RGB->YIQ
and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
q). I can then pass in this list to YIQ->RGB to get back the original
values. Or a use can enter (YIQ y i q) to test a conversion. It's just
something that makes it easier on the user. If this were C++, for
example, it would be easy to do with overloading. But I haven't gotten
through enough of your book, yet, to have figured it out on my own.

Thanks, Peter. Danke, Ranier.

Zach Beane

unread,
Apr 18, 2006, 8:48:01 PM4/18/06
to
wr...@stablecross.com (Bob Felts) writes:

> There's a method to my madness. Suppose I have two functions, RGB->YIQ
> and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
> q). I can then pass in this list to YIQ->RGB to get back the original
> values. Or a use can enter (YIQ y i q) to test a conversion. It's just
> something that makes it easier on the user. If this were C++, for
> example, it would be easy to do with overloading.

I would be inclined to use the multiple values mechanism instead.

(multiple-value-call #'yiq->rgb (rgb->yiq r g b)) => (values r g b)

Zach

M Jared Finder

unread,
Apr 19, 2006, 12:10:23 AM4/19/06
to
Bob Felts wrote:

> There's a method to my madness. Suppose I have two functions, RGB->YIQ
> and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
> q). I can then pass in this list to YIQ->RGB to get back the original
> values. Or a use can enter (YIQ y i q) to test a conversion. It's just
> something that makes it easier on the user. If this were C++, for
> example, it would be easy to do with overloading. But I haven't gotten
> through enough of your book, yet, to have figured it out on my own.
>
> Thanks, Peter. Danke, Ranier.

You want apply. Apply applies a function to a list of arguments
http://www.lisp.org/HyperSpec/Body/fun_apply.html

-- MJF

Ken Tilton

unread,
Apr 19, 2006, 12:11:57 AM4/19/06
to

Bob Felts wrote:
> Peter Seibel <pe...@gigamonkeys.com> wrote:
>
>
>>wr...@stablecross.com (Bob Felts) writes:
>>
>>
>>>Is there any way to write a function so that it can be called either as:
>>>
>>> (foo 1 2 3)
>>>
>>>or
>>> (foo '(1 2 3))
>>
>>It's seems unlikely to me that this is a good idea, but if you really
>>want to:
>>
>> (defun foo (a &optional b c)
>> (flet ((work (a b c) ...))
>> (if (consp a) (apply #'work a) (work a b c))))
>>
>
>
> There's a method to my madness. Suppose I have two functions, RGB->YIQ
> and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
> q). I can then pass in this list to YIQ->RGB to get back the original
> values.

You are looking for APPLY.

ken

--
Cells: http://common-lisp.net/project/cells/

"Have you ever been in a relationship?"
Attorney for Mary Winkler, confessed killer of her
minister husband, when asked if the couple had
marital problems.

Thomas A. Russ

unread,
Apr 19, 2006, 2:39:23 PM4/19/06
to

Bob Felts wrote:

> There's a method to my madness. Suppose I have two functions, RGB->YIQ
> and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
> q). I can then pass in this list to YIQ->RGB to get back the original
> values. Or a use can enter (YIQ y i q) to test a conversion. It's just
> something that makes it easier on the user. If this were C++, for
> example, it would be easy to do with overloading. But I haven't gotten
> through enough of your book, yet, to have figured it out on my own.
> Thanks, Peter. Danke, Ranier.

Well, setting aside all the APPLY-based solutions, I would ask why you
don't just make the argument always be a list? Unlike in C++, where
it's a real pain to produce new structure, with lists and the LIST
function it isn't hard.

For example, instead of
(RGB r g b)
you could either use
(RGB '(r g b)) ; if r,g,b are numeric literals
(RGB (list r g b)) ; ... otherwise

Adding the call to LIST is hardly a big problem. Then you could treat
all of the structures as lists. That would be pretty simple and it
would also serve to keep the values together in a single albeit simple
and generic data structure.

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

Bob Felts

unread,
Apr 19, 2006, 5:04:03 PM4/19/06
to
Thomas A. Russ <t...@sevak.isi.edu> wrote:

> Bob Felts wrote:
>
> > There's a method to my madness. Suppose I have two functions, RGB->YIQ
> > and YIQ->RGB. Then (RGB r g b) will return a list of three values (y i
> > q). I can then pass in this list to YIQ->RGB to get back the original
> > values. Or a use can enter (YIQ y i q) to test a conversion. It's just
> > something that makes it easier on the user. If this were C++, for
> > example, it would be easy to do with overloading. But I haven't gotten
> > through enough of your book, yet, to have figured it out on my own.
> > Thanks, Peter. Danke, Ranier.
>
> Well, setting aside all the APPLY-based solutions, I would ask why you
> don't just make the argument always be a list? Unlike in C++, where
> it's a real pain to produce new structure, with lists and the LIST
> function it isn't hard.

I agree it isn't hard, but there is the possibility of a bit of data
entry; it's easier to type (rgb 1 2 3) than it is to type (rgb '(1 2 3))

I've gone ahead an kept the interface to the user as (f x y z) and use
APPLY internally.

Ivan Boldyrev

unread,
Apr 20, 2006, 12:45:36 AM4/20/06
to
On 9449 day of my life Bob Felts wrote:
> Is there any way to write a function so that it can be called either as:
>
> (foo 1 2 3)
>
> or
> (foo '(1 2 3))
>
> such that 1 is bound, say, to x, 2 to y, and 3 to z?

If you need some speed:

(defun %foo (x y z)
;; Just an example
(sqrt (abs (* x y z))))

(defun foo (x &optional (y nil y-p) (z nil z-p))
(if (and y-p z-p)
(%foo x y z)
(apply #'%foo x)))

(define-compiler-macro foo (x &optional (y nil y-p) (z nil z-p))
(if (and y-p z-p)
`(%foo ,x ,y ,z)
`(apply #'%foo ,x)))

--
Ivan Boldyrev

Is 'morning' a gerund?

Tim X

unread,
Apr 23, 2006, 8:21:16 PM4/23/06
to
Rainer Joswig <jos...@lisp.de> writes:

> Am 18.04.2006 23:14 Uhr schrieb "Bob Felts" unter <wr...@stablecross.com> in
> 1he02hi.teqmou8dwdq8N%wr...@stablecross.com:
>
>> Is there any way to write a function so that it can be called either as:
>>
>> (foo 1 2 3)
>>
>> or
>> (foo '(1 2 3))
>>
>> such that 1 is bound, say, to x, 2 to y, and 3 to z?
>
> For example like this:
>
> (defun foo (&optional x y z)
> (if (listp x)
> (apply #'foo x)
> (+ x y z)))

Just nit picking, but wouldn't it be better as

(defun foo (x &optional y z)

It just strikes me that

(ddfun foo (&optional x y z)

could also be called with no arguments as in

(foo)

Tim

--
tcross (at) rapttech dot com dot au

Ari Johnson

unread,
Apr 23, 2006, 8:26:11 PM4/23/06
to
Tim X <ti...@nospam.dev.null> writes:

> Rainer Joswig <jos...@lisp.de> writes:
>> (defun foo (&optional x y z)
>> (if (listp x)
>> (apply #'foo x)
>> (+ x y z)))
>
> Just nit picking, but wouldn't it be better as
>
> (defun foo (x &optional y z)
>
> It just strikes me that
>
> (ddfun foo (&optional x y z)
>
> could also be called with no arguments as in
>
> (foo)

Not only that, but ...

(foo)
==> (listp nil) ==> (apply #'foo nil)

Right?

Rainer Joswig

unread,
Apr 23, 2006, 8:41:50 PM4/23/06
to
In article <87zmibx...@tiger.rapttech.com.au>,
Tim X <ti...@nospam.dev.null> wrote:

You also can check whether the parameters are supplied:

(defun foo (x &optional (y nil y-p) (z nil z-p))

(cond ((and y-p z-p)
(+ x y z))
...

--
http://lispm.dyndns.org/

0 new messages