[r6rs-discuss] [Formal] allow variable-length strings
From: Per Bothner <per_at_bothner.com>
Subject: [r6rs-discuss] [Formal] allow variable-length strings
Date: Tue, 20 Mar 2007 09:13:20 -0700
> The memory allocation for an N-character string is not a fixed multiple
> of N, unless one allocates a fixed 24 or 32 bits per character, which
> most Scheme implementations probably won't do. Hence a string will
> need a variable-sized buffer, which may need to be re-sized, for example
> after:
> (define str (make-string 1000 #\space))
> (string-set! str 500 #\x20000;)
>
> Since the allocated buffer is variable-sized, why not allow the number
> of characters to change?
I agree the awkwardness of string-set!, and "fixed number of
characters" limitation. There are two ways to go. One is to
allow length-changing mutation and add richer set of mutation
operations such as string-append!, string-replace!, etc.
Another is to make strings immutable, dropping string-set!,
string-fill!, string-upcase!, etc. If I have to choose, I'd
go for immutable solution.
> Consider also that string-set! is an awkward function for working with
> string. You almost never want to modify a single character in-place in
> a string. Instead, the most useful way to create a string is by
> appending to it. Hence I suggest adding:
>
> (string-append! str1 str2)
> (string-append! str1 ch2)
> or more generally:
> (string-append! str1 str-or-char ...)
I assume in general you construct a string from several
or more segments of strings or characters. Then, what
advantage string-append! has over the original string-append
or string output ports?
One advantage I can think of is that you can treat an
intermediate result of construction just like ordinary
string, which may be useful when you're reading input
a chunk at a time and every time you check whether you
have complete format of data. But it can be acheved
by modifying open-string-output-port so that the procedure
it returns takes an optional flag to specify not to clear
the internal buffer. For example:
(let loop ((buffer (make-string 0))
(chunk (read-from-network)))
(string-append! buffer chunk)
(if (input-complete? buffer)
buffer
(loop buffer (read-from-network))))
(receive (buffer finish) (open-string-output-port)
(let loop ((chunk (read-from-network)))
(display chunk buffer)
(if (input-complete? (finish #t)) ; suppose passing #t not to clear buf
(finish)
(loop (read-from-network)))))
Another special property of string-append! may be that
it can keep the identity of str1, but is there a case that
it is important?
As a side note, I wonder if the original report allows
an implementation to have a singleton empty string "".
For example, can (make-string 0) return a singleton ""?
The description of make-string does say "the returned
string is newly allocated", but the phrase "newly allocated"
seems ambiguous in case the structure have no elements.
For example, the description of 'reverse' in r5.92 says
"Returns a newly allocated list ..." but (reverse '()) may
not return something newly allocated, if I understand
correctly. (Maybe it's an oversight of the editor; the
descrption of 'append' in r5rs said "the resulting list is
always newly allocated", but in r5.92rs it says "the resulting
chain of pairs...".)
If we have string-append!, surely we can't have a singleton "".
--shiro
Received on Wed Mar 21 2007 - 15:33:10 UTC
This archive was generated by hypermail 2.3.0
: Wed Oct 23 2024 - 09:15:01 UTC