From: Ty Hoffman
Subject: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.16.09.53.347151@queets.com>
Hello,
          I'm just learning lisp, and would like know a more elegant way to
take the elements of a vector (all strings themselves) and concatenate
them together in a single string. MERGE, REDUCE, or CONCATENATE seem
close, but no cigar. This is how I've done it:

;create a vector of strings to use
(setf newvec (vector "fi" "fie" "fo" "fum"))


;start the string with the first element
(setf mystr (elt newvec 0))

;do the rest
(loop for i from 1 to (- (length newvec) 1)
        do(setf mystr (concatenate 'string mystr (elt newvec i))))

This looks mighty clunky to me. I would guess there's a better way. Anyone?

From: Peter Seibel
Subject: Re: vector to string conversion
Date: 
Message-ID: <m2zmqwt754.fsf@gigamonkeys.com>
Ty Hoffman <···@queets.com> writes:

> Hello,
>           I'm just learning lisp, and would like know a more elegant way to
> take the elements of a vector (all strings themselves) and concatenate
> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
> close, but no cigar. This is how I've done it:
>
> ;create a vector of strings to use
> (setf newvec (vector "fi" "fie" "fo" "fum"))
>
>
> ;start the string with the first element
> (setf mystr (elt newvec 0))
>
> ;do the rest
> (loop for i from 1 to (- (length newvec) 1)
>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>
> This looks mighty clunky to me. I would guess there's a better way. Anyone?

  (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"

  (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"

I'd prefer the latter since the former is likely to create a bunch of
intermediate strings.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Tayssir John Gabbour
Subject: Re: vector to string conversion
Date: 
Message-ID: <1125642672.330965.144320@z14g2000cwz.googlegroups.com>
Peter Seibel wrote:
> Ty Hoffman <···@queets.com> writes:
> >           I'm just learning lisp, and would like know a more elegant way to
> > take the elements of a vector (all strings themselves) and concatenate
> > them together in a single string. MERGE, REDUCE, or CONCATENATE seem
> > close, but no cigar. This is how I've done it:
> >
> > ;create a vector of strings to use
> > (setf newvec (vector "fi" "fie" "fo" "fum"))
> >
> >
> > ;start the string with the first element
> > (setf mystr (elt newvec 0))
> >
> > ;do the rest
> > (loop for i from 1 to (- (length newvec) 1)
> >         do(setf mystr (concatenate 'string mystr (elt newvec i))))
> >
> > This looks mighty clunky to me. I would guess there's a better way. Anyone?
>
>   (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
>
>   (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
>
> I'd prefer the latter since the former is likely to create a bunch of
> intermediate strings.

Too bad LOOP doesn't have something like a 'through' keyword, which
takes on any sequence. At whatever minor cost in runtime.

And I wonder why CONCATENATE uses &rest params, which limits it to
CALL-ARGUMENTS-LIMIT number of parameters.


Tayssir
From: Barry Margolin
Subject: Re: vector to string conversion
Date: 
Message-ID: <barmar-68A3FA.02572402092005@comcast.dca.giganews.com>
In article <························@z14g2000cwz.googlegroups.com>,
 "Tayssir John Gabbour" <···········@yahoo.com> wrote:

> And I wonder why CONCATENATE uses &rest params, which limits it to
> CALL-ARGUMENTS-LIMIT number of parameters.

How do you think it should work?  Should it just take a single list 
argument, and concatenate all its elements?  This is fine when you 
already have them in a list, but most of the time they come from 
distinct variables or expressions.  It's more natural to write:

(concatenate 'vector a b)

than

(concatenate 'vector (list a b))

This is consistent with most other functions that allow arbitrary 
numbers of arguments, like + and *.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Marco Antoniotti
Subject: Re: vector to string conversion
Date: 
Message-ID: <dFYRe.71$DJ5.74456@typhoon.nyu.edu>
Tayssir John Gabbour wrote:
> Peter Seibel wrote:
> 
>>Ty Hoffman <···@queets.com> writes:
>>
>>>          I'm just learning lisp, and would like know a more elegant way to
>>>take the elements of a vector (all strings themselves) and concatenate
>>>them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>>>close, but no cigar. This is how I've done it:
>>>
>>>;create a vector of strings to use
>>>(setf newvec (vector "fi" "fie" "fo" "fum"))
>>>
>>>
>>>;start the string with the first element
>>>(setf mystr (elt newvec 0))
>>>
>>>;do the rest
>>>(loop for i from 1 to (- (length newvec) 1)
>>>        do(setf mystr (concatenate 'string mystr (elt newvec i))))
>>>
>>>This looks mighty clunky to me. I would guess there's a better way. Anyone?
>>
>>  (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
>>
>>  (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
>>
>>I'd prefer the latter since the former is likely to create a bunch of
>>intermediate strings.
> 
> 
> Too bad LOOP doesn't have something like a 'through' keyword, which
> takes on any sequence. At whatever minor cost in runtime.

Shameless plug.  http://common-lisp.net/project/cl-enumeration :)

What is really a shame is that the thingies you need to extend LOOP are 
not standard.

Also, on a separate issue, I would really like to have

	(loop for x across L-or-V from 42 below 1024 ...)

or something like that.

SUBSEQing doesn't quite make it.

Cheers
--
Marco
From: Carl Shapiro
Subject: Re: vector to string conversion
Date: 
Message-ID: <ouyk6i03vwk.fsf@panix3.panix.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> I'd prefer the latter since the former is likely to create a bunch of
> intermediate strings.

A string stream is just as likely to create intermediate strings as
the concatenation approach.  If you care about this sort of a thing
you should preallocate the result string.

(defun do-it (sequence)
  (let ((new-string (make-string (reduce #'+ sequence :key #'length)))
	(start 0))
    (map nil #'(lambda (elt)
		 (replace new-string elt :start1 start)
		 (incf start (length elt)))
	 sequence)
    new-string))
From: Thomas F. Burdick
Subject: Re: vector to string conversion
Date: 
Message-ID: <xcvk6hzna3w.fsf@conquest.OCF.Berkeley.EDU>
Carl Shapiro <········@panix.com> writes:

> Peter Seibel <·····@gigamonkeys.com> writes:
> 
> > I'd prefer the latter since the former is likely to create a bunch of
> > intermediate strings.
> 
> A string stream is just as likely to create intermediate strings as
> the concatenation approach.

No, the reduce/concatenate approach is (almost) guaranteed to create
intermediate strings.  It would be possible for an implementation to
special case that, but it's *far* more likely (and useful) to optimize
string-output-streams.

> If you care about this sort of a thing you should preallocate the
> result string.

It depends.  If you want to make sure that you portably don't create
intermediate strings, then yes.  If you only care about that property
on a certain set of implementations, then maybe not.  In general, I'd
say the with-output-to-string approach is a nice compromise between
making the code easy for human consumption and realistically optimizable.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Rob Warnock
Subject: Re: vector to string conversion
Date: 
Message-ID: <0cudnZ2dnZ08d1bHnZ2dnX2Mhd6dnZ2dRVn-052dnZ0@speakeasy.net>
Thomas F. Burdick <···@conquest.OCF.Berkeley.EDU> wrote:
+---------------
| In general, I'd say the with-output-to-string approach is a
| nice compromise between making the code easy for human consumption
| and realistically optimizable.
+---------------

Especially since -- if you *do* happen to have a good guess as to
the result size -- you can provide WITH-OUTPUT-TO-STRING with an
initially-sized adjustable string to use as a starting point, as
in the example in the CLHS [slightly tweaked]:

    > (let ((string (make-array '(100) :element-type 'base-char
				       :fill-pointer 0
				       :adjustable t)))
	(with-output-to-string (s string)
	  (format s "Here's some output")
	  (format s " and some more output")
	  (format s " and some more.")
	  (format s " All done."))
	string)

    "Here's some output and some more output and some more. All done."
    > (length *)

    64
    > 


-Rob

p.s. CLHS-reading exercise for the newcomer: Why won't the following work?

      (with-output-to-string (s (make-array '(100) :element-type 'base-char
						   :fill-pointer 0
						   :adjustable t))
	(format s "Here's some output")
	(format s " and some more output")
	(format s " and some more.")
	(format s " All done."))

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.22.28.10.348918@queets.com>
On Fri, 02 Sep 2005 03:48:32 -0500, Rob Warnock wrote:

> Thomas F. Burdick <···@conquest.OCF.Berkeley.EDU> wrote:
> +---------------
> | In general, I'd say the with-output-to-string approach is a
> | nice compromise between making the code easy for human consumption
> | and realistically optimizable.
> +---------------
> 
> Especially since -- if you *do* happen to have a good guess as to
> the result size -- you can provide WITH-OUTPUT-TO-STRING with an
> initially-sized adjustable string to use as a starting point, as
> in the example in the CLHS [slightly tweaked]:
> 
>     > (let ((string (make-array '(100) :element-type 'base-char
> 				       :fill-pointer 0
> 				       :adjustable t)))
> 	(with-output-to-string (s string)
> 	  (format s "Here's some output")
> 	  (format s " and some more output")
> 	  (format s " and some more.")
> 	  (format s " All done."))
> 	string)
> 
>     "Here's some output and some more output and some more. All done."
>     > (length *)
> 
>     64
>     > 
> 
> 
> -Rob
> 
> p.s. CLHS-reading exercise for the newcomer: Why won't the following work?
> 
>       (with-output-to-string (s (make-array '(100) :element-type 'base-char
> 						   :fill-pointer 0
> 						   :adjustable t))
> 	(format s "Here's some output")
> 	(format s " and some more output")
> 	(format s " and some more.")
> 	(format s " All done."))
> 
> -----
> Rob Warnock			<····@rpw3.org>
> 627 26th Avenue			<URL:http://rpw3.org/>
> San Mateo, CA 94403		(650)572-2607

Not exactly sure, but since this works (as stated above):
(setf str (make-array '(100) :element-type 'base-char :fill-pointer 0
	:adjustable t))
(with-output-to-string (s str)
	(format s "Some kind of output..."))
str => "Some kind of output..."

I assume it has something to do with the output stream closing, and the
contents either not copied to a string, or copied to a temporary. Is that
in the ballpark? 
From: Tayssir John Gabbour
Subject: Re: vector to string conversion
Date: 
Message-ID: <1125654928.862246.66000@o13g2000cwo.googlegroups.com>
Ty Hoffman wrote:
> On Fri, 02 Sep 2005 03:48:32 -0500, Rob Warnock wrote:
> > p.s. CLHS-reading exercise for the newcomer: Why won't the following work?
> >
> >       (with-output-to-string (s (make-array '(100) :element-type 'base-char
> > 						   :fill-pointer 0
> > 						   :adjustable t))
> > 	(format s "Here's some output")
> > 	(format s " and some more output")
> > 	(format s " and some more.")
> > 	(format s " All done."))
>
> Not exactly sure, but since this works (as stated above):
> (setf str (make-array '(100) :element-type 'base-char :fill-pointer 0
> 	:adjustable t))
> (with-output-to-string (s str)
> 	(format s "Some kind of output..."))
> str => "Some kind of output..."
>
> I assume it has something to do with the output stream closing, and the
> contents either not copied to a string, or copied to a temporary. Is that
> in the ballpark?

By CLHS, he means the Common Lisp Hyperspec:
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_with-output-to-string.html

Tayssir
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.22.51.13.508021@queets.com>
On Fri, 02 Sep 2005 02:55:28 -0700, Tayssir John Gabbour wrote:

> Ty Hoffman wrote:
>> On Fri, 02 Sep 2005 03:48:32 -0500, Rob Warnock wrote:
>> > p.s. CLHS-reading exercise for the newcomer: Why won't the following work?
>> >
>> >       (with-output-to-string (s (make-array '(100) :element-type 'base-char
>> > 						   :fill-pointer 0
>> > 						   :adjustable t))
>> > 	(format s "Here's some output")
>> > 	(format s " and some more output")
>> > 	(format s " and some more.")
>> > 	(format s " All done."))
>>
>> Not exactly sure, but since this works (as stated above):
>> (setf str (make-array '(100) :element-type 'base-char :fill-pointer 0
>> 	:adjustable t))
>> (with-output-to-string (s str)
>> 	(format s "Some kind of output..."))
>> str => "Some kind of output..."
>>
>> I assume it has something to do with the output stream closing, and the
>> contents either not copied to a string, or copied to a temporary. Is that
>> in the ballpark?
> 
> By CLHS, he means the Common Lisp Hyperspec:
> http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_with-output-to-string.html
> 
> Tayssir

Thanks! I was wondering...
From: Harold
Subject: Re: vector to string conversion
Date: 
Message-ID: <1125682035.677533.27940@f14g2000cwb.googlegroups.com>
Copied to a temporary is more like it. Notice the last line in the
working version returns the value of the variable string.
From: Ray Dillinger
Subject: Re: vector to string conversion
Date: 
Message-ID: <SOFSe.11991$p%3.48005@typhoon.sonic.net>
Thomas F. Burdick wrote:
> Carl Shapiro <········@panix.com> writes:
> 
> 
>>Peter Seibel <·····@gigamonkeys.com> writes:
>>
>>
>>>I'd prefer the latter since the former is likely to create a bunch of
>>>intermediate strings.
>>
>>A string stream is just as likely to create intermediate strings as
>>the concatenation approach.
> 
> 
> No, the reduce/concatenate approach is (almost) guaranteed to create
> intermediate strings.  It would be possible for an implementation to
> special case that, but it's *far* more likely (and useful) to optimize
> string-output-streams.

This is one of the reasons why I think a rope implementation of
strings is inherently better.  A rope is essentially a tree that
leads to string segments.  When you join two strings, you get a
tree that just points to both of them, so concatenation is a
constant-time operation.

Of course, element access, which is constant-time in the array
representation, is logarithmic with a rope, so it's not all gravy.
But insertion, concatenation, and several other operations which
are linear with array representation are logarithmic or constant
in rope representation.

				Bear
From: Peter Seibel
Subject: Re: vector to string conversion
Date: 
Message-ID: <m2fyskwc2e.fsf@gigamonkeys.com>
Carl Shapiro <········@panix.com> writes:

> Peter Seibel <·····@gigamonkeys.com> writes:
>
>> I'd prefer the latter since the former is likely to create a bunch of
>> intermediate strings.
>
> A string stream is just as likely to create intermediate strings as
> the concatenation approach.  If you care about this sort of a thing
> you should preallocate the result string.

Well, I don't know about "just as likely". Unless there are some very
specific compiler macros in place, I'd expect REDUCE/CONCATENATE
version to make an intermediate string for each element of the
sequence. The WITH-OUTPUT-TO-STRING may have to adjust the underlying
array (which I'd count as creating an intermediate string) but if it's
grows the underlying array in some smart way such as doubling it
(maybe until it gets to some quite large maximum size), it's likely to
only have to do a few reallocations. Obviously there's no requirement
that the implementation of WITH-OUTPUT-TO-STRING behave like this but
it seems more likely than that there's a compiler macro that's going
to make the REDUCE/CONCATENATE version do the same thing.

-Peter
-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Carl Shapiro
Subject: Re: vector to string conversion
Date: 
Message-ID: <ouy64tg2pn1.fsf@panix3.panix.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> Well, I don't know about "just as likely". 
                                             
Both approaches will create intermediate strings.  Which one will
produce more is a function of your implementation, but garbage (or
over allocation) is inevitable unless you pre-size the destination
container.

There have been a number of arguments made against writing the
conversion function in the style I, and at least one other poster,
have.  It is claimed that other approaches yield shorter and therefore
more perspicuous function bodies.  Since the function in question is
already so short (in my case, eight lines of code), the claims to
clarity are weak.  There are advantages to the preallocation approach
such as storage conditions being signaled earlier by preallocating the
destination container and that the function has a simpler and more
favorable asymptotic complexity.  Given that the interface to this
function is far simpler for potential library users, at least in my
world, it is the clear winner.
From: Pascal Bourguignon
Subject: Re: vector to string conversion
Date: 
Message-ID: <87zmqwvzi9.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> Ty Hoffman <···@queets.com> writes:
>
>> Hello,
>>           I'm just learning lisp, and would like know a more elegant way to
>> take the elements of a vector (all strings themselves) and concatenate
>> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>> close, but no cigar. This is how I've done it:
>>
>> ;create a vector of strings to use
>> (setf newvec (vector "fi" "fie" "fo" "fum"))
>>
>>
>> ;start the string with the first element
>> (setf mystr (elt newvec 0))
>>
>> ;do the rest
>> (loop for i from 1 to (- (length newvec) 1)
>>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>>
>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
>
>   (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
>
>   (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
>
> I'd prefer the latter since the former is likely to create a bunch of
> intermediate strings.

I prefer:

[5]> (setf vector (vector "Hello" " " "World!" " " "Howdy!"))
#("Hello" " " "World!" " " "Howdy!")
[6]> (if (< (length vector) (- call-arguments-limit 2))
        (apply (function concatenate) 'string (coerce vector 'list))
        (reduce (lambda (x y) (concatenate 'string x y)) vector))
"Hello World! Howdy!"

Since it leaves concatenate a chance to allocate the resulting string once.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.17.43.43.219696@queets.com>
On Fri, 02 Sep 2005 06:56:30 +0200, Pascal Bourguignon wrote:

> Peter Seibel <·····@gigamonkeys.com> writes:
> 
>> Ty Hoffman <···@queets.com> writes:
>>
>>> Hello,
>>>           I'm just learning lisp, and would like know a more elegant way to
>>> take the elements of a vector (all strings themselves) and concatenate
>>> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>>> close, but no cigar. This is how I've done it:
>>>
>>> ;create a vector of strings to use
>>> (setf newvec (vector "fi" "fie" "fo" "fum"))
>>>
>>>
>>> ;start the string with the first element
>>> (setf mystr (elt newvec 0))
>>>
>>> ;do the rest
>>> (loop for i from 1 to (- (length newvec) 1)
>>>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>>>
>>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
>>
>>   (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
>>
>>   (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
>>
>> I'd prefer the latter since the former is likely to create a bunch of
>> intermediate strings.
> 
> I prefer:
> 
> [5]> (setf vector (vector "Hello" " " "World!" " " "Howdy!"))
> #("Hello" " " "World!" " " "Howdy!")
> [6]> (if (< (length vector) (- call-arguments-limit 2))
>         (apply (function concatenate) 'string (coerce vector 'list))
>         (reduce (lambda (x y) (concatenate 'string x y)) vector))
> "Hello World! Howdy!"
> 
> Since it leaves concatenate a chance to allocate the resulting string once.

Thanks! This one will take me a while to digest. 
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.17.37.17.73495@queets.com>
On Fri, 02 Sep 2005 04:39:51 +0000, Peter Seibel wrote:

> Ty Hoffman <···@queets.com> writes:
> 
>> Hello,
>>           I'm just learning lisp, and would like know a more elegant way to
>> take the elements of a vector (all strings themselves) and concatenate
>> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>> close, but no cigar. This is how I've done it:
>>
>> ;create a vector of strings to use
>> (setf newvec (vector "fi" "fie" "fo" "fum"))
>>
>>
>> ;start the string with the first element
>> (setf mystr (elt newvec 0))
>>
>> ;do the rest
>> (loop for i from 1 to (- (length newvec) 1)
>>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>>
>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
> 
>   (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
> 
>   (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
> 
> I'd prefer the latter since the former is likely to create a bunch of
> intermediate strings.
> 
> -Peter

Wow, thanks! Very interesting language. The second version creates an
output stream (s), then loops thru the vector writing each element to the
output stream? Is this correct? 
From: tichy
Subject: Re: vector to string conversion
Date: 
Message-ID: <1125733617.894755.295380@g44g2000cwa.googlegroups.com>
Hi.
> (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s)))

I would prefer:

(with-output-to-string (*standard-output*) (map nil #'princ (vector
"ab" "cd" "ef")))

It's one character shorter ;-)
Btw, i would prefer WRITE-STRING over PRINC (because it's more specific
here).
From: Kent M Pitman
Subject: Re: vector to string conversion
Date: 
Message-ID: <uvf1gxu4e.fsf@nhplace.com>
"tichy" <·····@o2.pl> writes:

> Hi.
> > (with-output-to-string (s)
> >   (loop for x across (vector "ab" "cd" "ef")
> >         do (princ x s)))
> 
> I would prefer:
> 
> (with-output-to-string (*standard-output*)
>   (map nil #'princ (vector "ab" "cd" "ef")))
> 
> It's one character shorter ;-)
> Btw, i would prefer WRITE-STRING over PRINC
> (because it's more specific here).

Given a suitably defined CURRY, left as a fun exercise for the reader
(but expect it to be about 3-4 lines of code you do one place and then
can use many places):

 (reduce (curry #'concatenate 'string) '("foo" "bar" "baz"))
 => "foobarbaz"

APPLY would work here, too, except that if the list gets long, APPLY
will fail (due to LAMBDA-PARAMETERS-LIMIT being exceeded), while REDUCE
will not (because the items in the list are reduced pairwise using
the given function).
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.03.08.10.20.936612@queets.com>
On Fri, 02 Sep 2005 04:39:51 +0000, Peter Seibel wrote:

> Ty Hoffman <···@queets.com> writes:
> 
>> Hello,
>>           I'm just learning lisp, and would like know a more elegant way to
>> take the elements of a vector (all strings themselves) and concatenate
>> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>> close, but no cigar. This is how I've done it:
>>
>> ;create a vector of strings to use
>> (setf newvec (vector "fi" "fie" "fo" "fum"))
>>
>>
>> ;start the string with the first element
>> (setf mystr (elt newvec 0))
>>
>> ;do the rest
>> (loop for i from 1 to (- (length newvec) 1)
>>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>>
>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
> 
>   (reduce #'(lambda (x y) (concatenate 'string x y)) (vector "ab" "cd" "ef")) ==> "abcdef"
> 
>   (with-output-to-string (s) (loop for x across (vector "ab" "cd" "ef") do (princ x s))) ==> "abcdef"
> 
> I'd prefer the latter since the former is likely to create a bunch of
> intermediate strings.
> 
> -Peter


Since you were impressively the first to respond, I'm going to go buy your
book now, Mr Seidels...er, Seibel. 
From: Rainer Joswig
Subject: Re: vector to string conversion
Date: 
Message-ID: <joswig-172645.07152602092005@news-europe.giganews.com>
In article <······························@queets.com>,
 Ty Hoffman <···@queets.com> wrote:

> Hello,
>           I'm just learning lisp, and would like know a more elegant way to
> take the elements of a vector (all strings themselves) and concatenate
> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
> close, but no cigar. This is how I've done it:
> 
> ;create a vector of strings to use
> (setf newvec (vector "fi" "fie" "fo" "fum"))
> 
> 
> ;start the string with the first element
> (setf mystr (elt newvec 0))
> 
> ;do the rest
> (loop for i from 1 to (- (length newvec) 1)
>         do(setf mystr (concatenate 'string mystr (elt newvec i))))

Above does cons a lot.

> This looks mighty clunky to me. I would guess there's a better way. Anyone?

Maybe something like this (using a fat LOOP):

(defun concatenate-vector-of-strings (vector)
  (loop with length = (reduce '+ vector :key 'length)
        with new-string = (make-string length)
        for start = 0 then (+ start (length string))
        and i from 0 below (length vector)
        for string = (aref vector i)
        do (setf (subseq new-string start) string)
        finally (return new-string)))
From: Rainer Joswig
Subject: Re: vector to string conversion
Date: 
Message-ID: <BF3DBBE0.16545%joswig@lisp.de>
Am 02.09.2005 7:15 Uhr schrieb "Rainer Joswig" unter <······@lisp.de> in
····························@news-europe.giganews.com:

> In article <······························@queets.com>,
>  Ty Hoffman <···@queets.com> wrote:
> 
>> Hello,
>>           I'm just learning lisp, and would like know a more elegant way to
>> take the elements of a vector (all strings themselves) and concatenate
>> them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>> close, but no cigar. This is how I've done it:
>> 
>> ;create a vector of strings to use
>> (setf newvec (vector "fi" "fie" "fo" "fum"))
>> 
>> 
>> ;start the string with the first element
>> (setf mystr (elt newvec 0))
>> 
>> ;do the rest
>> (loop for i from 1 to (- (length newvec) 1)
>>         do(setf mystr (concatenate 'string mystr (elt newvec i))))
> 
> Above does cons a lot.
> 
>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
> 
> Maybe something like this (using a fat LOOP):
> 
> (defun concatenate-vector-of-strings (vector)
>   (loop with length = (reduce '+ vector :key 'length)
>         with new-string = (make-string length)
>         for start = 0 then (+ start (length string))
>         and i from 0 below (length vector)
>         for string = (aref vector i)
>         do (setf (subseq new-string start) string)
>         finally (return new-string)))

(defun concatenate-vector-of-strings (vector)
  (loop with new-string = (make-string (reduce '+ vector :key 'length))
        for start = 0 then (+ start (length string))
        and string across vector
        do (setf (subseq new-string start) string)
        finally (return new-string)))
From: Peder O. Klingenberg
Subject: Re: vector to string conversion
Date: 
Message-ID: <kshdd4vsgk.fsf@beto.netfonds.no>
Ty Hoffman <···@queets.com> writes:

> This looks mighty clunky to me. I would guess there's a better way. Anyone?

Others have mentioned good ways of doing this, but I haven't (yet)
seen any mention of FORMAT:

CL-USER> (defparameter vec (vector "foo" "bar" "baz"))
VEC
CL-USER> (format nil "~{~a~}" (coerce vec 'list))
"foobarbaz"

Seems very concise to me.

...Peder...
-- 
I wish a new life awaited _me_ in some off-world colony.
From: Andreas Thiele
Subject: Re: vector to string conversion
Date: 
Message-ID: <df97i7$6sh$01$1@news.t-online.com>
"Peder O. Klingenberg" <·····@news.klingenberg.no> schrieb im Newsbeitrag
···················@beto.netfonds.no...
> Ty Hoffman <···@queets.com> writes:
>
> > This looks mighty clunky to me. I would guess there's a better way.
Anyone?
>
> Others have mentioned good ways of doing this, but I haven't (yet)
> seen any mention of FORMAT:
>
> CL-USER> (defparameter vec (vector "foo" "bar" "baz"))
> VEC
> CL-USER> (format nil "~{~a~}" (coerce vec 'list))
> "foobarbaz"
>
> Seems very concise to me.
>
> ...Peder...
> --
> I wish a new life awaited _me_ in some off-world colony.
>

Aarg :))

This is what I just wanted to suggest. But additionally a tiny hint for a
newbie:

(format nil "~{~a~^, ~}" (coerce vec 'list))

will give

"foo, bar, baz"

With ~^ you can easily introduce separating strings _between_ your string
elements, something I need quite often.

Andreas
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.22.53.49.340175@queets.com>
On Fri, 02 Sep 2005 11:55:16 +0200, Andreas Thiele wrote:

> 
> "Peder O. Klingenberg" <·····@news.klingenberg.no> schrieb im Newsbeitrag
> ···················@beto.netfonds.no...
>> Ty Hoffman <···@queets.com> writes:
>>
>> > This looks mighty clunky to me. I would guess there's a better way.
> Anyone?
>>
>> Others have mentioned good ways of doing this, but I haven't (yet)
>> seen any mention of FORMAT:
>>
>> CL-USER> (defparameter vec (vector "foo" "bar" "baz"))
>> VEC
>> CL-USER> (format nil "~{~a~}" (coerce vec 'list))
>> "foobarbaz"
>>
>> Seems very concise to me.
>>
>> ...Peder...
>> --
>> I wish a new life awaited _me_ in some off-world colony.
>>
> 
> Aarg :))
> 
> This is what I just wanted to suggest. But additionally a tiny hint for a
> newbie:
> 
> (format nil "~{~a~^, ~}" (coerce vec 'list))
> 
> will give
> 
> "foo, bar, baz"
> 
> With ~^ you can easily introduce separating strings _between_ your string
> elements, something I need quite often.
> 
> Andreas

Funny, exactly what I was looking to do. See my last response!
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.02.22.44.23.326398@queets.com>
On Fri, 02 Sep 2005 09:28:43 +0200, Peder O. Klingenberg wrote:

> Ty Hoffman <···@queets.com> writes:
> 
>> This looks mighty clunky to me. I would guess there's a better way. Anyone?
> 
> Others have mentioned good ways of doing this, but I haven't (yet)
> seen any mention of FORMAT:
> 
> CL-USER> (defparameter vec (vector "foo" "bar" "baz"))
> VEC
> CL-USER> (format nil "~{~a~}" (coerce vec 'list))
> "foobarbaz"
> 
> Seems very concise to me.
> 
> ...Peder...

Yes, very concise indeed. What about efficiency, as other posts have
mentioned? A lot of temporaries created, etc?

Also, this version lets me insert a delimiter between the elements easily,
which is something else I was fooling around with:

(defparameter vec (vector "fi" "fie" "fo" "fum"))
(format nil "~{~a~^*~}" (coerce vec 'list))
"fi*fie*fo*fum"

Thank you very much!
From: Harold
Subject: Re: vector to string conversion
Date: 
Message-ID: <1125681825.872288.9670@f14g2000cwb.googlegroups.com>
The #'format form is probably implemented as a  with-output-to-string
surrounding some kind of loop, if I had to guess. So it would have the
performance "issues" of the first with-output-to-string solution that
was posted. Of course, that may be plenty fast for you.

If you wanted, you could write an implementation of #'format that
optimizes by trying to guess the length of the output and pre-allocate
a string of that size. Maybe some of the Lisp implementors in the group
can weigh in.
From: Peder O. Klingenberg
Subject: Re: vector to string conversion
Date: 
Message-ID: <ksvf1j216i.fsf@beto.netfonds.no>
Ty Hoffman <···@queets.com> writes:

> What about efficiency, as other posts have mentioned? A lot of
> temporaries created, etc?

I haven't checked, and generally I don't worry about such things until
I have to.

...Peder...
-- 
I wish a new life awaited _me_ in some off-world colony.
From: Wade Humeniuk
Subject: Re: vector to string conversion
Date: 
Message-ID: <NAZRe.214304$9A2.84277@edtnps89>
Ty Hoffman wrote:
 > Hello,
 >           I'm just learning lisp, and would like know a more elegant way to
 > take the elements of a vector (all strings themselves) and concatenate
 > them together in a single string. MERGE, REDUCE, or CONCATENATE seem
 > close, but no cigar. This is how I've done it:
 >
 > ;create a vector of strings to use
 > (setf newvec (vector "fi" "fie" "fo" "fum"))
 >
 >
 > ;start the string with the first element
 > (setf mystr (elt newvec 0))
 >
 > ;do the rest
 > (loop for i from 1 to (- (length newvec) 1)
 >         do(setf mystr (concatenate 'string mystr (elt newvec i))))
 >
 > This looks mighty clunky to me. I would guess there's a better way. Anyone?

IMO, yes, it's simply

(vector "fi" "fie" "fo" "fum")

CL-USER 1 > (vector "fi" "fie" "fo" "fum")
#("fi" "fie" "fo" "fum")

CL-USER 2 >

Technically the strings are ordered (concatenated into a sequence).
What is the harm of just leaving them in this form?  For what
purpose do you need them in a collapsed sequence (string)?
Leaving them in this efficient form can have many benefits.

Wade
From: Ty Hoffman
Subject: Re: vector to string conversion
Date: 
Message-ID: <pan.2005.09.03.07.59.50.720639@queets.com>
On Fri, 02 Sep 2005 14:46:05 +0000, Wade Humeniuk wrote:

> Ty Hoffman wrote:
>  > Hello,
>  >           I'm just learning lisp, and would like know a more elegant way to
>  > take the elements of a vector (all strings themselves) and concatenate
>  > them together in a single string. MERGE, REDUCE, or CONCATENATE seem
>  > close, but no cigar. This is how I've done it:
>  >
>  > ;create a vector of strings to use
>  > (setf newvec (vector "fi" "fie" "fo" "fum"))
>  >
>  >
>  > ;start the string with the first element
>  > (setf mystr (elt newvec 0))
>  >
>  > ;do the rest
>  > (loop for i from 1 to (- (length newvec) 1)
>  >         do(setf mystr (concatenate 'string mystr (elt newvec i))))
>  >
>  > This looks mighty clunky to me. I would guess there's a better way. Anyone?
> 
> IMO, yes, it's simply
> 
> (vector "fi" "fie" "fo" "fum")
> 
> CL-USER 1 > (vector "fi" "fie" "fo" "fum")
> #("fi" "fie" "fo" "fum")
> 
> CL-USER 2 >
> 
> Technically the strings are ordered (concatenated into a sequence).
> What is the harm of just leaving them in this form?  For what
> purpose do you need them in a collapsed sequence (string)?
> Leaving them in this efficient form can have many benefits.
> 
> Wade

Of course you are right. I have no practical reason to do this, nor do I
have any real performance constraints. This is just a learning exercise.If
I were to do something like this in the real world I would probably leave
the vectors alone until I had to output. Let's say I had a bunch of string
values I wanted to sort, dedupe, etc., and in the end output to a file
with delimiters for easy DB loading, I would probably manipulate as
elements of a vector, then format out to a file placing the delimiters.