5.5.5 Strings

Strings are fixed-length sequences of characters. They can be created
by calling constructor procedures, but they can also literally get
entered at the REPL or in Scheme source files.

Strings always carry the information about how many characters they are
composed of with them, so there is no special end-of-string character,
like in C. That means that Scheme strings can contain any character,
even the ‘#\nul’ character ‘\0’.

To use strings efficiently, you need to know a bit about how Guile
implements them. In Guile, a string consists of two parts, a head and
the actual memory where the characters are stored. When a string (or
a substring of it) is copied, only a new head gets created, the memory
is usually not copied. The two heads start out pointing to the same
memory.

When one of these two strings is modified, as with string-set!,
their common memory does get copied so that each string has its own
memory and modifying one does not accidently modify the other as well.
Thus, Guile's strings are `copy on write'; the actual copying of their
memory is delayed until one string is written to.

This implementation makes functions like substring very
efficient in the common case that no modifications are done to the
involved strings.

If you do know that your strings are getting modified right away, you
can use substring/copy instead of substring. This
function performs the copy immediately at the time of creation. This
is more efficient, especially in a multi-threaded program. Also,
substring/copy can avoid the problem that a short substring
holds on to the memory of a very large original string that could
otherwise be recycled.

If you want to avoid the copy altogether, so that modifications of one
string show up in the other, you can use substring/shared. The
strings created by this procedure are called mutation sharing
substrings since the substring and the original string share
modifications to each other.