Lisp HUG Maillist Archive

(apply #'concatenate 'string

What is the maximum length of a list of strings (s) that Lispworks
(Windows) can 
(apply #'concatenate 'string s) ?

I ask so that I can avoid a "stack overflow" or "out of memory" errors
with concatenation of long lists of strings, from 
(mapcar #'string [list of chars])
obtained when reading text files.

In other words how can I write an efficient

(defun apply-concatenate-to-long-string (s)
  (let ((maxlength #+MCL ? #+Lispworks ?))
    (if (< (length s) maxlength)
      (apply #'concatenate 'string s)
      (do ((s s (rest s))
           (r ""))
          ((endp s) r)
        (setf r (concatenate 'string r (first s))))
      )))

?

Thanks,
Sheldon

Re: (apply #'concatenate 'string

On 9291 day of my life Sheldon Ball wrote:
> What is the maximum length of a list of strings (s) that Lispworks
> (Windows) can
> (apply #'concatenate 'string s) ?

There is constant CALL-ARGUMENTS-LIMIT

-- 
Ivan Boldyrev

                                      Life!  Don't talk to me about life.


Re: (apply #'concatenate 'string

On Sat, 12 Nov 2005 05:31:50 +0100, Sheldon Ball <s.ball@anvita.info>  
wrote:

> What is the maximum length of a list of strings (s) that Lispworks
> (Windows) can
> (apply #'concatenate 'string s) ?
>
> I ask so that I can avoid a "stack overflow" or "out of memory" errors
> with concatenation of long lists of strings, from
> (mapcar #'string [list of chars])
> obtained when reading text files.
>
> In other words how can I write an efficient
>
> (defun apply-concatenate-to-long-string (s)
>    (let ((maxlength #+MCL ? #+Lispworks ?))
>      (if (< (length s) maxlength)
>        (apply #'concatenate 'string s)
>        (do ((s s (rest s))
>             (r ""))
>            ((endp s) r)
>          (setf r (concatenate 'string r (first s))))
>        )))
>
> ?
>
> Thanks,
> Sheldon

There is a maximum of I think 255 arguments to a function.
If you exceed this limit the problem is probaly that you
are using Lisp wrong.
Seems your means of reading text files is the real cuprit here.
Why do you read a file character by character and then convert it
to a list of characters and then concatenate?
This is EXTREMLY inefficient.
If you want to read it character by character.. fine
I suppose you have a reason.
But there are much better ways of converting it to a string.
How about something along the following lines:

(defun read-a-file-char-by-char (pathname)
   (check-type pathname pathname)
   (let ((char-array (make-array 100 :element-type 'character :adustable t  
:fill-pointer 0)))
     (with-open-file (stream pathname)
       (do ((char (read-line stream) (read-line stream nil 'eof)))
           ((not (characterp char)))
         (vector-push-extend char char-array)))
     (coerce char-array 'string)))

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


Re: (apply #'concatenate 'string

On Sat, 12 Nov 2005 10:33:22 +0100, "John Thingstad" <john.thingstad@chello.no> wrote:

> There is a maximum of I think 255 arguments to a function.

There's no reason to guess, this is governed by the standard:

  <http://www.lispworks.com/documentation/HyperSpec/Body/v_call_a.htm>

And note that this could as well change in upcoming releases so you
better don't hardcode something like 255 in your apps.


Re: (apply #'concatenate 'string

On Fri, 11 Nov 2005 20:31:50 -0800, Sheldon Ball <s.ball@anvita.info> wrote:

> In other words how can I write an efficient
>
> (defun apply-concatenate-to-long-string (s)

Here are two other ways of doing it (untested):

  (format nil "~{~A~}" string-list)

  (defun string-list-to-string (string-list)
    (let ((total-size 0))
      (dolist (string string-list)
        (incf total-size (length string)))
      (let ((result-string (make-sequence 'simple-string total-size))
            (curr-pos 0))
        (dolist (string string-list)
          (replace result-string string :start1 curr-pos)
          (incf curr-pos (length string)))
        result-string)))

See also WITH-OUTPUT-TO-STRING in the CLHS.

Cheers,
Edi.


Re: (apply #'concatenate 'string

On Sat, 12 Nov 2005 12:07:33 +0100, "Arthur Lemmens" <alemmens@xs4all.nl> wrote:

> Instead of:
>
>>     (let ((total-size 0))
>>       (dolist (string string-list)
>>         (incf total-size (length string)))
>
> I used:
>
>     (let ((total-size (reduce #'+ string-list :key #'length)))

Yep, that's better because it's more terse.

> and instead of:
>
>>       (let ((result-string (make-sequence 'simple-string total-size))
>
> I used:
>
>     (let ((result-string (make-string total-size)))

Yeah, I copied my example (slightly modified) from a function JP
Massar submitted for CL-PPCRE - the SIMPLE-STRING part is an artefact
of that and it shouldn't be there.

Cheers,
Edi.


Re: (apply #'concatenate 'string

On 9291 day of my life Sheldon Ball wrote:
> I ask so that I can avoid a "stack overflow" or "out of memory" errors
> with concatenation of long lists of strings, from
> (mapcar #'string [list of chars])
> obtained when reading text files.

If you want to get string from list of chars, just use COERCE:

(coerce (list #\a #\b #\c) 'string)
 => "abc"

If you want to concatenate lot of string of list, you may use FORMAT

(format nil "~{~A~}"   (list "1" "23" "456"))
 => "123456"

But its effectiveness is implementation-dependent.

-- 
Ivan Boldyrev

                                                  Is 'morning' a gerund?


Updated at: 2020-12-10 08:50 UTC