From: jblazi
Subject: how to concatenate strings?
Date: 
Message-ID: <pan.2004.08.28.19.26.25.63000@hotmail.com>
A rather elementary question, isn't it and some members of the group will
again laugh about me ("Haven's you learn *any* Lisp in all those years...?").

I should like to write a function f that works like this:

(f <string1> <string2>)

String2 should be appended to string1 and string1 should be destructively
modified (this is the part I do not know how to do). The most elegant
solution would be a format statement with string1 as the destination but
then the fillpointer business enters the game and I do not understand
this. I also tried nconc but then I need lists and that make this solution
a bit clumsy.

(I simply want to avoid constructions like
(setf x (concatenate 'string x y)).)

And another question: Let us suppose my master string, which will be
appended to, is called buf. Will something like

(setq buf (make-string 200000))

speed the appending up? (The maybe it is not necessairy to allocate more
memory again and again.)

TIA,

jb

From: Matthew Danish
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <20040828193821.GK8087@mapcar.org>
On Sat, Aug 28, 2004 at 09:26:25PM +0200, jblazi wrote:
> String2 should be appended to string1 and string1 should be destructively
> modified (this is the part I do not know how to do). 

Strings can not normally be destructively appended.

> The most elegant solution would be a format statement with string1 as
> the destination but then the fillpointer business enters the game and
> I do not understand this. I also tried nconc but then I need lists and
> that make this solution a bit clumsy.

It's very simple.  You construct your string object using this call:

  (make-array 0 :element-type 'character :adjustable t :fill-pointer 0)

Then you may use FORMAT or VECTOR-PUSH-EXTEND.  All that the
fill-pointer does is indicate where characters should be inserted.  If
you leave it alone, it will be incremented by the operations, and
everything should work as you expect.

> And another question: Let us suppose my master string, which will be
> appended to, is called buf. Will something like
> 
> (setq buf (make-string 200000))
> 
> speed the appending up? (The maybe it is not necessairy to allocate more
> memory again and again.)

You could do this, and use REPLACE to set subsequences of the string
efficiently.

For your application, though, it might be more efficient and simpler to
use string-streams, for example:

(with-output-to-string (stream)
  (write-string "Hello World" stream))

==> "Hello World"

That should give you a number of options to consider.

-- 
;;;; Matthew Danish -- user: mrd domain: cmu.edu
;;;; OpenPGP public key: C24B6010 on keyring.debian.org
From: Björn Lindberg
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <hcsacwehil8.fsf@my.nada.kth.se>
Matthew Danish <·······@andrew.cmu.edu> writes:

> On Sat, Aug 28, 2004 at 09:26:25PM +0200, jblazi wrote:
> > String2 should be appended to string1 and string1 should be destructively
> > modified (this is the part I do not know how to do). 
> 
> Strings can not normally be destructively appended.
> 
> > The most elegant solution would be a format statement with string1 as
> > the destination but then the fillpointer business enters the game and
> > I do not understand this. I also tried nconc but then I need lists and
> > that make this solution a bit clumsy.
> 
> It's very simple.  You construct your string object using this call:
> 
>   (make-array 0 :element-type 'character :adjustable t :fill-pointer 0)

(To the original poster:)

To add to what Matthew said; just define a function
make-adjustable-string, and you won't have to think about fill
pointers at all:

(defun make-adjustable-string (&optional (string ""))
  (make-array (length string)
              :element-type 'character
              :adjustable t
              :fill-pointer t
              :initial-contents string))

Have you seen the chapter on strings in the CL cookbook?

http://cl-cookbook.sourceforge.net/strings.html


Bj�rn
From: Ron Garret
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <rNOSPAMon-CC4DE8.13075329082004@nntp1.jpl.nasa.gov>
In article <·····························@hotmail.com>,
 jblazi <······@hotmail.com> wrote:

> A rather elementary question, isn't it and some members of the group will
> again laugh about me ("Haven's you learn *any* Lisp in all those years...?").
> 
> I should like to write a function f that works like this:
> 
> (f <string1> <string2>)
> 
> String2 should be appended to string1 and string1 should be destructively
> modified (this is the part I do not know how to do).

Do you know about vector-push-extend?

? (setf s (make-array '(0) :element-type 'character :fill-pointer t 
:adjustable t))
""
? (stringp s)
T
? (vector-push-extend #\a s)
0
? s
"a"
? (vector-push-extend #\b s)
1
? s
"ab"
? 

rg
From: jblazi
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <pan.2004.08.30.10.46.59.94000@hotmail.com>
On Sun, 29 Aug 2004 13:07:53 -0700, Ron Garret wrote:
> Do you know about vector-push-extend?
> 
> ? (setf s (make-array '(0) :element-type 'character :fill-pointer t 
> :adjustable t))
> ""
> ? (stringp s)
> T
> ? (vector-push-extend #\a s)
> 0
> ? s
> "a"
> ? (vector-push-extend #\b s)
> 1
> ? s
> "ab"
> ? 
> 
> rg

Thank you all. Finally I chose this solution:

(setq buf (make-array 200000 :element-type 'character adjustable t :fill-pointer 0))
(defun astr (x) (format buf "~A" x))

Is it inferior?

TIA,
jb
From: Mark McConnell
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <d3aed052.0408301157.13b6be24@posting.google.com>
jblazi <······@hotmail.com> wrote in message news:<·····························@hotmail.com>...
> Thank you all. Finally I chose this solution:
> 
> (setq buf (make-array 200000 :element-type 'character adjustable t :fill-pointer 0))
> (defun astr (x) (format buf "~A" x))

Can you make the 200000 smaller for all or most of your applications?
From: Matthew Danish
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <20040830200011.GO8087@mapcar.org>
On Mon, Aug 30, 2004 at 12:47:03PM +0200, jblazi wrote:
> Thank you all. Finally I chose this solution:
> (setq buf (make-array 200000 :element-type 'character adjustable t :fill-pointer 0))
> (defun astr (x) (format buf "~A" x))
> Is it inferior?

Yes, there is no reason to pre-allocate a 200000 character string,
unless you actually need it.  FORMAT and VECTOR-PUSH-EXTEND will
automatically adjust the size of the string for you.

-- 
;;;; Matthew Danish -- user: mrd domain: cmu.edu
;;;; OpenPGP public key: C24B6010 on keyring.debian.org
From: Marco Antoniotti
Subject: Re: how to concatenate strings?
Date: 
Message-ID: <691Zc.66$D5.76155@typhoon.nyu.edu>
Matthew Danish wrote:

> On Mon, Aug 30, 2004 at 12:47:03PM +0200, jblazi wrote:
> 
>>Thank you all. Finally I chose this solution:
>>(setq buf (make-array 200000 :element-type 'character adjustable t :fill-pointer 0))
>>(defun astr (x) (format buf "~A" x))
>>Is it inferior?
> 
> 
> Yes, there is no reason to pre-allocate a 200000 character string,
> unless you actually need it.  FORMAT and VECTOR-PUSH-EXTEND will
> automatically adjust the size of the string for you.

Let's also not forget the optional EXTENSION parameter to 
VECTOR-PUSH-EXTEND.  That is also a useful thing.

Cheers
--
Marco