Strings
Strings are immutable sequences of grapheme clusters. All string operations use the string/ prefix. @"..." creates a mutable string.
Access and length
(length "hello") # => 5 (grapheme count)
(string/size-of "hello") # => 5 (byte count)
(get "hello" 0) # => "h" (grapheme cluster)
(get "hello" -1) # => "o" (negative indexes)
(slice "hello" 1 4) # => "ell"
Grapheme count and byte count differ for multi-byte characters:
(length "👋🏽") # => 1 (one grapheme cluster)
(string/size-of "👋🏽") # => 8 (4+4 bytes UTF-8)
Concatenation
# string converts all args to strings and concatenates
(string "hello " "world") # => "hello world"
(string "count: " 42) # => "count: 42"
# join a collection with a separator
(string/join ["a" "b" "c"] ",") # => "a,b,c"
# format with placeholders
(string/format "{} + {} = {}" 1 2 3) # => "1 + 2 = 3"
Search and test
(string/find "hello" "ll") # => 2 (grapheme index, or nil if not found)
(string/find "hello" "xx") # => nil
(string/find "hello" "lo" 3) # => 3 (with optional start offset)
(string/index-of "hello" "ll") # => 2 (alias for string/find)
(string/contains? "hello" "ell") # => true
(string/starts-with? "hello" "he") # => true
(string/ends-with? "hello" "lo") # => true
string/find returns the grapheme index of the first occurrence, or nil if the substring is not found. An optional third argument sets the start offset. string/index-of is an alias.
Transformation
(string/upcase "hello") # => "HELLO"
(string/downcase "HELLO") # => "hello"
(string/trim " hi ") # => "hi"
(string/replace "foo-bar" "-" "_") # => "foo_bar"
(string/repeat "-" 20) # => "--------------------"
Splitting
(string/split "a,b,c" ",") # => ["a" "b" "c"] (returns array)
(string/split "one two three" " ") # => ["one" "two" "three"]
(string/split "a,,b" ",") # => ["a" "" "b"] (empty strings between consecutive delimiters)
string/split returns an array of substrings. Consecutive delimiters produce empty strings in the result. The delimiter cannot be empty.
Mutable @strings
@"..." creates a mutable string. get, put, length, push, and pop are all grapheme-indexed. put mutates in place and returns the @string.
(def s @"hello")
(get s 0) # => "h"
(put s 0 "H") # mutates and returns s; s is now @"Hello"
(push s "!") # mutates and returns s; s is now @"Hello!"
(pop s) # => "!" (removes and returns last)
Conversion
(thaw "hello") # => @"hello"
(freeze @"hello") # => "hello"
(string 42) # => "42"
(string :foo) # => "foo" (no colon)