From: Brian Kendig
Subject: Need help with some simple APPLY troubles...
Date: 
Message-ID: <1992May19.221546.19425@Princeton.EDU>
It all started when I got sick of typing (concatenate 'string ...)
all the time, so I whipped me up a macro:

	(defmacro cat (&rest strs)
	  `(concatenate 'string ,@strs))

Later on I made a function that takes a variable number of arguments;
in some cases, I want to cat the arguments together with a colon in
front of them.  My first shot at it was:

	(defun f (&rest args)
	  ...
	  (write-text (eval `(cat ":" ,@args)))
	  ...

(where write-text is a function that takes a string and does something
with it).  But this uses an eval, and doesn't look too pretty besides.
So I tried using 'apply', which would do the trick nicely, wouldn't it?

	  (write-text (cat ":" (apply #'cat args)))

Still a little ugly, but nicer than the last one.  But this gives me
an error:

	>>Error: Wrong number of arguments to CAT

... that didn't make any sense to me at all until I checked Steele's
CLtL2, which says that the function used in 'apply' can't be a macro.

I'm kinda up the creek here.  Any ideas on how I can send a variable
number of arguments to a macro?

Alternatively, I could use a direct call to 'concatenate', but it
requires an argument of its own (which is why I created the macro in
the first place, so I wouldn't keep forgetting to type the argument).
But I don't know how to put that argument in a call to 'apply',
because

	(apply #'concatenate 'string args)

fails for obvious reasons (it tries to use 'string as the list).  What
is the proper syntax of what I'm trying to do here?

Thanks for any and all help!

     << Brian >>

-- 
| Brian S. Kendig       --/\-- Tri     ········@phoenix.Princeton.EDU, @PUCC
| Computer Science BSE  |/  \| Quad  You gave your life to become the person
| Princeton University  /____\ clubs    you are right now.  Was it worth it?

From: Adam Farquhar
Subject: Re: Need help with some simple APPLY troubles...
Date: 
Message-ID: <l1j8erINNaf0@bathtub.cs.utexas.edu>
In article <······················@Princeton.EDU> you write:
>It all started when I got sick of typing (concatenate 'string ...)
>all the time, so I whipped me up a macro:
>
>	(defmacro cat (&rest strs)
>	  `(concatenate 'string ,@strs))
>
>Later on I made a function that takes a variable number of arguments;
>in some cases, I want to cat the arguments together with a colon in
>front of them.  My first shot at it was:
>
>	(defun f (&rest args)
>	  ...
>	  (write-text (eval `(cat ":" ,@args)))
>	  ...
>
>I'm kinda up the creek here.  Any ideas on how I can send a variable
>number of arguments to a macro?

&REST allows you to use a variable number of arguments to your macro.
What you are trying to do, however, is vary the expansion of your
macro with each call to F.  Macros do eval/compile-time source code
transformations, functions are the appropriate objects if you want to
vary the behavior at run-time.  I.e. what you really want is a
FUNCTION, not a MACRO.  As a general rule, if you need to eval a
macro, you should be using a function instead.

>	(apply #'concatenate 'string args)
>
>fails for obvious reasons (it tries to use 'string as the list).  What
>is the proper syntax of what I'm trying to do here?
>

Actually this IS the proper syntax, and it DOES NOT fail.  APPLY does
just what you want it to!  One obvious solution to your problem is:

(defun cat (&rest args)
  (apply #'concatenate 'string args))

(defun f (&rest args)
  ...
  (write-text
   (apply #'cat ":" args))
  ...
  )

- Adam Farquhar.
From: Barry Margolin
Subject: Re: Need help with some simple APPLY troubles...
Date: 
Message-ID: <vciosINNmq1@early-bird.think.com>
In article <······················@Princeton.EDU> ········@light.Princeton.EDU (Brian Kendig) writes:
>It all started when I got sick of typing (concatenate 'string ...)
>all the time, so I whipped me up a macro:
>
>	(defmacro cat (&rest strs)
>	  `(concatenate 'string ,@strs))

Your problems would all go away if you made this a function:

(defun cat (&rest strs)
  (apply #'concatenate 'string strs))

You can then use (apply #'cat ...)
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Mark Feblowitz
Subject: Re: Need help with some simple APPLY troubles...
Date: 
Message-ID: <MDF0.92May20141707@shemesh.GTE.com>
Wouldn't it be:

	(apply #'concatenate (list 'string args))

??
--
Mark Feblowitz   GTE Laboratories, Inc., 40 Sylvan Rd.  Waltham, MA 02254
						(617) 466-2947
CSNET:  ··········@GTE.com
UUCP:   ··········@bunny.UUCP       old UUCP:  harvard!bunny!mfeblowitz
From: Len Charest
Subject: APPLY takes multiple args (was Re: Need some help...
Date: 
Message-ID: <1992May20.214924.3122@jpl-devvax.jpl.nasa.gov>
In reply to the question of how to CONCATENATE a list of strings...

In article <··················@shemesh.GTE.com>, ····@GTE.com (Mark Feblowitz) writes:
|> Wouldn't it be:
|> 	(apply #'concatenate (list 'string args))

No--args is already a list. As Adam Farquhar (········@cs.utexas.edu) has already pointed out, the APPLY form was correct as originally posted. Only the *last* argument to APPLY must be a list.

Some correct forms for concatenating a list of strings:
(apply #'concatenate 'string args)
(apply #'concatenate 'string 1st-arg rest-args)
(apply #'concatenate (cons 'string args))
(apply #'concatenate (list* 'string args))
..................................................
                                  Len Charest, Jr.
                 JPL Artificial Intelligence Group
                          ·······@aig.jpl.nasa.gov
From: Danny Brewer
Subject: Re: Need help with some simple APPLY troubles...
Date: 
Message-ID: <274@farallonfarallon.com>
In article <··················@shemesh.GTE.com>, ····@GTE.com (Mark Feblowitz) writes:
> 
> Wouldn't it be:
> 
> 	(apply #'concatenate (list 'string args))
> 

No,

   (apply #'concatenate 'string args)

would be correct.  Only the last argument to apply should be a list
of additional arguments.  For example:

   (setf args (list 'x 'y 'z))

   (apply #'fn args)           ==>  (fn 'x 'y 'z)
   (apply #'fn 'a args)        ==>  (fn 'a 'x 'y 'z)
   (apply #'fn 'a 'b 'c args)  ==>  (fn 'a 'b 'c 'x 'y 'z)

   (apply #'fn args args)      ==>  (fn '(x y z) 'x 'y 'z)

Danny
·····@farallon.com