Strings & Characters
Core String Operations
string-append
Concatenate strings together.
(string-append "hello" " " "world") ; => "hello world"
(string-append "a" "b" "c") ; => "abc"string-length
Return the number of characters in a string.
(string-length "hello") ; => 5
(string-length "") ; => 0
(string-length "héllo") ; => 5
(string-length "日本語") ; => 3string-ref
Return the character at a given index.
(string-ref "hello" 0) ; => #\h
(string-ref "hello" 4) ; => #\osubstring
Extract a substring by start and end character index.
(substring "hello" 1 3) ; => "el"
(substring "hello" 0 5) ; => "hello"
(substring "héllo" 1 2) ; => "é"str
Convert any value to its string representation.
(str 42) ; => "42"
(str #t) ; => "#t"
(str '(1 2 3)) ; => "(1 2 3)"format
Format a string with ~a placeholders.
(format "~a is ~a" "Sema" "great") ; => "Sema is great"
(format "~a + ~a = ~a" 1 2 3) ; => "1 + 2 = 3"Slash-Namespaced String Operations
string/split
Split a string by a delimiter.
(string/split "a,b,c" ",") ; => ("a" "b" "c")
(string/split "hello world" " ") ; => ("hello" "world")string/join
Join a list of strings with a separator.
(string/join '("a" "b" "c") ", ") ; => "a, b, c"
(string/join '("x" "y") "-") ; => "x-y"string/trim
Remove whitespace from both ends.
(string/trim " hello ") ; => "hello"
(string/trim "\thello\n") ; => "hello"string/trim-left
Remove whitespace from the left.
(string/trim-left " hi") ; => "hi"string/trim-right
Remove whitespace from the right.
(string/trim-right "hi ") ; => "hi"string/upper
Convert string to uppercase.
(string/upper "hello") ; => "HELLO"string/lower
Convert string to lowercase.
(string/lower "HELLO") ; => "hello"string/capitalize
Capitalize the first character.
(string/capitalize "hello") ; => "Hello"string/title-case
Capitalize the first character of each word.
(string/title-case "hello world") ; => "Hello World"string/contains?
Test if a string contains a substring.
(string/contains? "hello" "ell") ; => #t
(string/contains? "hello" "xyz") ; => #fstring/starts-with?
Test if a string starts with a prefix.
(string/starts-with? "hello" "he") ; => #t
(string/starts-with? "hello" "lo") ; => #fstring/ends-with?
Test if a string ends with a suffix.
(string/ends-with? "hello" "lo") ; => #t
(string/ends-with? "hello" "he") ; => #fstring/replace
Replace all occurrences of a substring.
(string/replace "hello" "l" "r") ; => "herro"
(string/replace "aaa" "a" "b") ; => "bbb"string/index-of
Return the byte index of the first occurrence of a substring, or nil if not found.
(string/index-of "hello" "ll") ; => 2
(string/index-of "hello" "xyz") ; => nilstring/chars
Convert a string to a list of characters.
(string/chars "abc") ; => (#\a #\b #\c)string/repeat
Repeat a string N times.
(string/repeat "ab" 3) ; => "ababab"
(string/repeat "-" 5) ; => "-----"string/pad-left
Pad a string on the left to a given width.
(string/pad-left "42" 5 "0") ; => "00042"
(string/pad-left "hi" 5) ; => " hi"string/pad-right
Pad a string on the right to a given width.
(string/pad-right "hi" 5) ; => "hi "
(string/pad-right "42" 5 "0") ; => "42000"string/number?
Test if a string represents a valid number.
(string/number? "42") ; => #t
(string/number? "3.14") ; => #t
(string/number? "hello") ; => #fstring/map
Apply a character function to each character in a string, returning a new string.
(string/map char-upcase "hello") ; => "HELLO"string/reverse
Reverse a string.
(string/reverse "hello") ; => "olleh"Unicode & Encoding
string/byte-length
Return the UTF-8 byte length of a string (as opposed to character count from string-length). Useful for understanding the actual memory footprint — emoji and CJK characters use more bytes than ASCII.
(string/byte-length "hello") ; => 5 (ASCII: 1 byte each)
(string/byte-length "héllo") ; => 6 (é is 2 bytes in UTF-8)
(string/byte-length "日本語") ; => 9 (CJK: 3 bytes each)
(string/byte-length "😀") ; => 4 (emoji: 4 bytes)Compare with string-length which counts characters:
(string-length "😀") ; => 1 (one character)
(string/byte-length "😀") ; => 4 (four bytes)string/codepoints
Return a list of Unicode codepoint integers for each character in a string. This reveals the internal structure of composed characters and emoji sequences.
(string/codepoints "ABC") ; => (65 66 67)
(string/codepoints "é") ; => (233)
(string/codepoints "😀") ; => (128512)Emoji that appear as a single glyph are often multiple codepoints joined by Zero Width Joiner (U+200D = 8205):
;; 👨👩👦 is actually 👨 + ZWJ + 👩 + ZWJ + 👦
(string/codepoints "👨👩👦") ; => (128104 8205 128105 8205 128102)
;; 👋🏽 is 👋 + skin tone modifier
(string/codepoints "👋🏽") ; => (128075 127997)string/from-codepoints
Construct a string from a list of Unicode codepoint integers. This is the inverse of string/codepoints and enables building emoji programmatically by combining codepoints.
(string/from-codepoints (list 65 66 67)) ; => "ABC"
(string/from-codepoints (list 233)) ; => "é"Build emoji by combining people with ZWJ (8205):
;; Build a family: 👨 + ZWJ + 👩 + ZWJ + 👧
(string/from-codepoints (list 128104 8205 128105 8205 128103))
;; => 👨👩👧
;; Build a profession: 👩 + ZWJ + 💻
(string/from-codepoints (list 128105 8205 128187))
;; => 👩💻
;; Add skin tone: 👋 + modifier
(string/from-codepoints (list 128075 127997))
;; => 👋🏽
;; Build flags from Regional Indicators (A=127462):
(string/from-codepoints (list 127475 127476))
;; => 🇳🇴 (NO = Norway)Roundtrip any string through codepoints:
(string/from-codepoints (string/codepoints "Hello 世界"))
;; => "Hello 世界"string/normalize
Normalize a string to a Unicode normalization form. Supported forms: :nfc, :nfd, :nfkc, :nfkd (as keywords or strings).
- NFC — Canonical Decomposition, followed by Canonical Composition (most common)
- NFD — Canonical Decomposition
- NFKC — Compatibility Decomposition, followed by Canonical Composition
- NFKD — Compatibility Decomposition
;; NFC: combine decomposed characters
;; e + combining acute accent → é
(string/normalize "e\u0301" :nfc) ; => "é"
;; NFD: decompose composed characters
(string-length (string/normalize "é" :nfd)) ; => 2 (e + combining accent)
;; NFKC/NFKD: compatibility decomposition (ligatures, etc.)
(string/normalize "\uFB01" :nfkc) ; => "fi" (fi ligature → two letters)
;; String form names also work
(string/normalize "e\u0301" "NFC") ; => "é"string/foldcase
Apply Unicode case folding to a string. Useful for case-insensitive comparisons and normalization. Uses full Unicode-aware lowercasing.
(string/foldcase "HELLO") ; => "hello"
(string/foldcase "Hello World") ; => "hello world"
(string/foldcase "Straße") ; => "straße"
(string/foldcase "ΩΜΕΓΑ") ; => "ωμεγα"string-ci=?
Case-insensitive string equality comparison. Compares two strings after applying case folding to both.
(string-ci=? "Hello" "hello") ; => #t
(string-ci=? "ABC" "abc") ; => #t
(string-ci=? "CAFÉ" "café") ; => #t
(string-ci=? "hello" "world") ; => #fCharacters
Character literals are written with the #\ prefix.
#\a ; character literal
#\space ; named character: space
#\newline ; named character: newline
#\tab ; named character: tabchar->integer
Convert a character to its Unicode code point.
(char->integer #\A) ; => 65
(char->integer #\a) ; => 97integer->char
Convert a Unicode code point to a character.
(integer->char 65) ; => #\A
(integer->char 955) ; => #\λchar-alphabetic?
Test if a character is alphabetic.
(char-alphabetic? #\a) ; => #t
(char-alphabetic? #\5) ; => #fchar-numeric?
Test if a character is numeric.
(char-numeric? #\5) ; => #t
(char-numeric? #\a) ; => #fchar-whitespace?
Test if a character is whitespace.
(char-whitespace? #\space) ; => #t
(char-whitespace? #\a) ; => #fchar-upper-case?
Test if a character is uppercase.
(char-upper-case? #\A) ; => #t
(char-upper-case? #\a) ; => #fchar-upcase
Convert a character to uppercase.
(char-upcase #\a) ; => #\Achar-downcase
Convert a character to lowercase.
(char-downcase #\Z) ; => #\zchar->string
Convert a character to a single-character string.
(char->string #\a) ; => "a"string->char
Convert a single-character string to a character.
(string->char "a") ; => #\aCharacter Comparison (R7RS)
char=?
Character equality.
(char=? #\a #\a) ; => #t
(char=? #\a #\b) ; => #fchar<?
Character less-than (by code point).
(char<? #\a #\b) ; => #tchar>?
Character greater-than.
(char>? #\b #\a) ; => #tchar<=?
Character less-than-or-equal.
(char<=? #\a #\b) ; => #t
(char<=? #\a #\a) ; => #tchar>=?
Character greater-than-or-equal.
(char>=? #\b #\a) ; => #tchar-ci=?
Case-insensitive character equality.
(char-ci=? #\A #\a) ; => #tType Conversions
string->number
Parse a string as a number.
(string->number "42") ; => 42
(string->number "3.14") ; => 3.14number->string
Convert a number to a string.
(number->string 42) ; => "42"
(number->string 3.14) ; => "3.14"string->symbol
Convert a string to a symbol.
(string->symbol "foo") ; => foosymbol->string
Convert a symbol to a string.
(symbol->string 'foo) ; => "foo"string->keyword
Convert a string to a keyword.
(string->keyword "name") ; => :namekeyword->string
Convert a keyword to a string.
(keyword->string :name) ; => "name"string->list
Convert a string to a list of characters.
(string->list "abc") ; => (#\a #\b #\c)list->string
Convert a list of characters to a string.
(list->string '(#\h #\i)) ; => "hi"