# (lispkit string)

Strings are sequences of characters. In LispKit, characters are UTF-16 code units. Strings are written as sequences of characters enclosed within quotation marks (`"`). Within a string literal, various escape sequences represent characters other than themselves. Escape sequences always start with a backslash `\`:

* `\a`: alarm (U+0007)
* `\b`: backspace (U+0008)
* : character tabulation (U+0009)
* : linefeed (U+000A)
* : return (U+000D)
* `\"`: double quote (U+0022)
* `\\`: backslash (U+005C)
* `\|`: vertical line (U+007C)
* `\`*line-end*: used for encoding multi-line string literals
* `\x`*hex-scalar-value*`;`: specified character

The result is unspecified if any other character in a string occurs after a backslash.

Except for a line ending, any character outside of an escape sequence stands for itself in the string literal. A line ending which is preceded by a backslash expands to nothing and can be used to encode multi-line string literals.

```scheme
(display "The word \"recursion\" has many meanings.")  ⇒
The word "recursion" has many meanings.
(display "Another example:\ntwo lines of text.")  ⇒
Another example:
two lines of text.
(display "\x03B1; is named GREEK SMALL LETTER ALPHA.")  ⇒
α is named GREEK SMALL LETTER ALPHA.
```

The length of a string is the number of characters, i.e. UTF-16 code units, that it contains. This number is an exact, non-negative integer that is fixed when the string is created. The valid indexes of a string are the exact non-negative integers less than the length of the string. The first character of a string has index 0, the second has index 1, and so on.

Some of the procedures that operate on strings ignore the difference between upper and lower case. The names of the versions that ignore case end with `-ci` (for “case insensitive”).

LispKit only supports mutable strings.

## Basic constructors and procedures

**(make-string&#x20;*****k*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(make-string&#x20;*****k char*****)**

The `make-string` procedure returns a newly allocated string of length *k*. If *char* is given, then all the characters of the string are initialized to *char*, otherwise the contents of the string are unspecified.

**(string&#x20;*****char ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns a newly allocated string composed of the arguments. It is analogous to procedure `list`.

**(list->string&#x20;*****list*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns a newly allocated string composed of the characters contained in *list*.

**(object->string&#x20;*****obj*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns a string representation of *obj*. This procedure converts the object to a human-readable string format, similar to what would be displayed when the object is printed.

**(string-ref&#x20;*****str k*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

The `string-ref` procedure returns character *k* of string *str* using zero-origin indexing. It is an error if *k* is not a valid index of string *str*.

**(string-set!&#x20;*****str k char*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

The `string-set!` procedure stores *char* in element *k* of string *str*. It is an error if *k* is not a valid index of string *str*.

**(string-length&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns the number of characters in the given string *str*.

## Predicates

**(string?&#x20;*****obj*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if *obj* is a string; otherwise returns `#f`.

**(string-empty?&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if *str* is an empty string, i.e. a string of length 0. Otherwise, `string-empty?` returns `#f`.

**(string=?&#x20;*****str ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if all the strings have the same length and contain exactly the same characters in the same positions; otherwise `string=?` returns `#f`.

**(string\<?&#x20;*****str ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string>?&#x20;*****str ...*****)**\
\&#xNAN;**(string<=?&#x20;*****str ...*****)**\
\&#xNAN;**(string>=?&#x20;*****str ...*****)**

These procedures return `#t` if their arguments are (respectively): monotonically increasing, monotonically decreasing, monotonically non-decreasing, or monotonically non-increasing. These predicates are transitive. They compare strings in a lexicographic fashion; i.e. `string<?` implements a the lexicographic ordering on strings induced by the ordering `char<?` on characters. If two strings differ in length but are the same up to the length of the shorter string, the shorter string would be considered to be lexicographically less than the longer string.

A pair of strings satisfies exactly one of `string<?`, `string=?`, and `string>?`. A pair of strings satisfies `string<=?` if and only if they do not satisfy `string>?`. A pair of strings satisfies `string>=?` if and only if they do not satisfy `string<?`.

**(string-ci=? )**    <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if, after case-folding, all the strings have the same length and contain the same characters in the same positions; otherwise `string-ci=?` returns `#f`.

**(string-ci\<?&#x20;*****str ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-ci<=?&#x20;*****str ...*****)**\
\&#xNAN;**(string-ci>?&#x20;*****str ...*****)**\
\&#xNAN;**(string-ci>=?&#x20;*****str ...*****)**

These procedures compare strings in a case-insensitive fashion. The "-ci" procedures behave as if they applied `string-foldcase` to their arguments before invoking the corresponding procedures without "-ci".

**(string-contains?&#x20;*****str sub*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if string *str* contains string *sub*; returns `#f` otherwise.

**(string-prefix?&#x20;*****str sub*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if string *str* has string *sub* as a prefix; returns `#f` otherwise.

**(string-suffix?&#x20;*****str sub*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns `#t` if string *str* has string *sub* as a suffix; returns `#f` otherwise.

## Composing and extracting strings

Many of the following procedures accept an optional *start* and *end* argument as their last two arguments. If both or one of these optional arguments are not provided, *start* defaults to `0` and *end* defaults to the length of the corresponding string.

**(string-contains&#x20;*****str sub*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-contains&#x20;*****str sub start*****)**\
\&#xNAN;**(string-contains&#x20;*****str sub start end*****)**

This procedure checks whether string *sub* is contained in string *str* within the index range *start* to *end*. It returns the first index into *str* at which *sub* is fully contained within *start* and *end*. If *sub* is not contained in the substring of *str*, then `#f` is returned.

**(substring&#x20;*****str start end*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

The `substring` procedure returns a newly allocated string formed from the characters of string *str* beginning with index *start* and ending with index *end*. This is equivalent to calling `string-copy` with the same arguments, but is provided for backward compatibility and stylistic flexibility.

**(string-append&#x20;*****str ...*****)**    <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Returns a newly allocated string whose characters are the concatenation of the characters in the given strings *str ...*.

**(string-concatenate&#x20;*****list*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-concatenate&#x20;*****list sep*****)**

Returns a newly allocated string whose characters are the concatenation of the characters in the strings contained in *list*. *sep* is either a character or string, which, if provided, is used as a separator between two strings that get concatenated. It is an error if *list* is not a proper list containing only strings as elements.

**(string-upcase&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-downcase&#x20;*****str*****)**\
\&#xNAN;**(string-titlecase&#x20;*****str*****)**\
\&#xNAN;**(string-foldcase&#x20;*****str*****)**

These procedures apply the Unicode full string uppercasing, lowercasing, titlecasing, and case-folding algorithms to their argument string *str* and return the result as a newly allocated string. It is not guaranteed that the resulting string has the same lenght like *str*. Language-sensitive string mappings and foldings are not used.

**(string-normalize-diacritics&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Procedure `string-normalize-diacritics` transforms the given string *str* by normalizing diacritics and returning the result as a newly allocated string.

```scheme
(string-normalize-diacritics "Meet Chloë at São Paulo Café")
⇒  "Meet Chloe at Sao Paulo Cafe"
```

**(string-normalize-separators&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-normalize-separators&#x20;*****str sep*****)**\
\&#xNAN;**(string-normalize-separators&#x20;*****str sep cset*****)**

Procedure `string-normalize-separators` normalizes string *str* by replacing sequences of separation characters from character set *cset* with string or character *sep*. If *sep* is not provided, `" "` is used as a default. If *cset* is not provided, all unicode newline and whitespace characters are used as a default for *cset*. *cset* is either a string of separation characters or a character set as defined by library `(lispkit char-set)`.

**(string-encode-named-chars&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-encode-named-chars&#x20;*****str required-only?*****)**

Procedure `string-encode-named-chars` returns a new string, replacing characters with their corresponding named XML entity in string *str*. If parameter `required-only?` is set to `#f`, all characters with corresponding named XML entities are being replaced, otherwise only the required characters are replaced.

```scheme
(string-encode-named-chars "<one> & two = 3")
⇒  "&LT;one&gt; &AMP; two &equals; 3"
(string-encode-named-chars "<one> & two = 3" #t)
⇒  "&lt;one&gt; &amp; two = 3"
```

**(string-decode-named-chars&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Procedure `string-decode-named-chars` returns a new string, replacing named XML entities with their corresponding character.

```scheme
(string-decode-named-chars "2&Hat;&lcub;3&rcub; &equals; 8")
⇒  "2^{3} = 8"
```

**(string-copy&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-copy&#x20;*****str start*****)**\
\&#xNAN;**(string-copy&#x20;*****str start end*****)**

Returns a newly allocated copy of the part of the given string *str* between *start* and *end*. The default for *start* is 0, for *end* it is the length of *str*. Calling `string-copy` is equivalent to calling `substring` with the same arguments. `substring` is provided primarily for backward compatibility.

**(string-split&#x20;*****str sep allow-empty?*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Procedure `string-split` splits string *str* using the separator *sep* and returns a list of the component strings, in order. *sep* is either a string or a character. Boolean argument *allow-empty?* determines whether empty component strings are dropped. *allow-empty?* is `#t` by default.

```scheme
(string-split "name-|-street-|-zip-|-city-|-" "-|-")  ⇒  ("name" "street" "zip" "city" "")
(string-split "name-|-street-|-zip-|-city-|-" "-|-" #f)  ⇒  ("name" "street" "zip" "city")
```

**(string-trim&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-trim&#x20;*****str chars*****)**

Returns a newly allocated string by removing all characters from the beginning and end of string *str* that are contained in *chars*. *chars* is either a string or it is a character set. If *chars* is not provided, whitespaces and newlines are being removed.

```scheme
(string-trim "  lispkit is fun ")                             ⇒  "lispkit is fun"
(string-trim "________" "_")                                  ⇒  ""
(string-trim "712+72=784" (char-set->string char-set:digit))  ⇒  "+72="
(string-trim "712+72=784" char-set:digit)                     ⇒  "+72="
```

**(string-pad-right&#x20;*****str char k*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-pad-right&#x20;*****str char k force-length?*****)**

Procedure `string-pad-right` returns a newly allocated string created by padding string *str* at the beginning of the string with character *char* until it is of length *k*. If *k* is less than the length of string *str*, the resulting string gets truncated at length *k* if boolean argument *force-length?* is `#t`; otherwise, the string *str* gets returned as is.

```scheme
(string-pad-right "scheme" #\space 8)    ⇒  "scheme  "
(string-pad-right "scheme" #\x 4)        ⇒  "scheme"
(string-pad-right "scheme" #\x 4 #t)     ⇒  "sche"
(string-pad-right "scheme" "_" 10)       ⇒  "scheme____"
```

**(string-pad-left&#x20;*****str char k*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-pad-left&#x20;*****str char k force-length?*****)**

Procedure `string-pad-left` returns a newly allocated string created by padding string *str* at the beginning of the string with character *char* until it is of length *k*. If *k* is less than the length of string *str*, the resulting string gets truncated at length *k* if boolean argument *force-length?* is `#t`; otherwise, the string *str* gets returned as is.

```scheme
(string-pad-left "scheme" #\space 8)    ⇒  "  scheme"
(string-pad-left "scheme" #\x 4)        ⇒  "scheme"
(string-pad-left "scheme" #\x 4 #t)     ⇒  "heme"
(string-pad-left "scheme" "_" 10)       ⇒  "____scheme"
```

**(string-pad-center&#x20;*****str char k*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-pad-center&#x20;*****str char k force-length?*****)**

Procedure `string-pad-center` returns a newly allocated string created by padding string *str* at the beginning and end with character *char* until it is of length *k*, such that *str* is centered in the middle. If *k* is less than the length of string *str*, the resulting string gets truncated at length *k* if boolean argument *force-length?* is `#t`; otherwise, the string *str* gets returned as is.

```scheme
(string-pad-center "scheme" #\space 8)  ⇒  " scheme "
(string-pad-center "scheme" #\x 4)      ⇒  "scheme"
(string-pad-center "scheme" #\x 4 #t)   ⇒  "heme"
(string-pad-center "scheme" "_" 10)     ⇒  "__scheme__"
```

## Manipulating strings

**(string-replace!&#x20;*****str sub repl*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-replace!&#x20;*****str sub repl start*****)**\
\&#xNAN;**(string-replace!&#x20;*****str sub repl start end*****)**

Replaces all occurences of string *sub* in string *str* between indices *start* and *end* with string *repl* and returns the number of occurences of *sub* that were replaced.

**(string-replace-first!&#x20;*****str sub repl*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-replace-first!&#x20;*****str sub repl start*****)**\
\&#xNAN;**(string-replace-first!&#x20;*****str sub repl start end*****)**

Replaces the first occurence of string *sub* in string *str* between indices *start* and *end* with string *repl* and returns the index at which the first occurence of *sub* was replaced.

**(string-insert!&#x20;*****str repl*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-insert!&#x20;*****str repl start*****)**\
\&#xNAN;**(string-insert!&#x20;*****str repl start end*****)**

Replaces the part of string *str* between index *start* and *end* with string *repl*. The default for *start* is 0, for *end* it is *start* (i.e. if not provided, *end* is equals to *start*). If both *start* and *end* are not provided, `string-insert!` inserts *repl* at the beginning of *str*. If *start* is provided alone (without *end*), `string-insert!` inserts *repl* at position *start*.

```scheme
(define s "Zenger is my name")
(string-insert! s "Matthias ")
s  ⇒  "Matthias Zenger is my name"
(string-insert! s "has always been" 16 18)
s  ⇒  "Matthias Zenger has always been my name"
```

**(string-append!&#x20;*****str other ...*****)**    <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Appends the strings *other*, ... to mutable string *str* in the given order.

**(string-copy!&#x20;*****to at from*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-copy!&#x20;*****to at from start*****)**\
\&#xNAN;**(string-copy!&#x20;*****to at from start end*****)**

Copies the characters of string *from* between index *start* and *end* to string *to*, starting at index *at*. If the source and destination overlap, copying takes place as if the source is first copied into a temporary string and then into the destination. It is an error if *at* is less than zero or greater than the length of string *to*. It is also an error if `(- (string-length to) at)` is less than `(- end start)`.

**(string-fill!&#x20;*****str fill*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string-fill!&#x20;*****str fill start*****)**\
\&#xNAN;**(string-fill!&#x20;*****str fill start end*****)**

The `string-fill!` procedure stores *fill* in the elements of string *str* between index *start* and *end*. It is an error if *fill* is not a character.

## Iterating over strings

**(string-map&#x20;*****proc str ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

The `string-map` procedure applies procedure *proc* element-wise to the characters of the strings *str ...* and returns a string of the results, in order. If more than one string *str* is given and not all strings have the same length, `string-map` terminates when the shortest string runs out. It is an error if *proc* does not accept as many arguments as there are strings and returns a single character.

```scheme
(string-map char-foldcase "AbdEgH")  ⇒  "abdegh"
(string-map (lambda (c) (integer->char (+ 1 (char->integer c)))) "HAL")  ⇒  "IBM"
```

**(string-for-each&#x20;*****proc str ...*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

The arguments to `string-for-each` are like the arguments to `string-map`, but `string-for-each` calls *proc* for its side effects rather than for its values. Unlike `string-map`, `string-for-each` is guaranteed to call *proc* on the characters of the strings in order from the first character to the last. If more than one string *str* is given and not all strings have the same length, `string-for-each` terminates when the shortest string runs out. It is an error for *proc* to mutate any of the strings. It is an error if *proc* does not accept as many arguments as there are strings.

## Converting strings

**(string->list&#x20;*****str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">\
\&#xNAN;**(string->list&#x20;*****str start*****)**\
\&#xNAN;**(string->list&#x20;*****str start end*****)**

The `string->list` procedure returns a list of the characters of string *str* between *start* and *end* preserving the order of the characters.

## Input/Output

**(read-file&#x20;*****path*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Reads the text file at *path* and stores its content in a newly allocated string which gets returned by `read-file`.

**(write-file&#x20;*****path str*****)** <img src="/files/STqjiJsrexexyFklGQwH" alt="" data-size="line">

Writes the characters of string *str* into a new text file at *path*. `write-file` returns `#t` if the file could be written successfully; otherwise `#f` is returned.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.lisppad.app/libraries/lispkit/lispkit-string.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
