std/string
Functions for String, the type of lists of Unicode scalar values kept
as UTF-8.
Lengths, indexes, and slices count codepoints (Unicode scalar
values), not bytes and not graphemes: "é" written as e and a
combining accent is two codepoints. byte_size counts UTF-8 bytes.
Access and searches count scalars. Negative at indexes count from the
end, as in slice; search bounds must be between zero and length.
Access, taking and traversals decode once, costing O(bytes) time and
O(scalars) cells, even for early access. Searches decode both strings and
use naive matching: O(n*m) comparisons and O(n+m) cells. Int arithmetic
and callbacks add their costs. No grapheme or normalization policy.
to_upper, to_lower, and capitalise use the simple case mappings of
Unicode (core.to_upper and core.to_lower): each codepoint changes to
one codepoint, with no locale, so "ß" stays "ß". trim and
the other trim functions take out the characters of Unicode
Pattern_White_Space: U+0009 to U+000D, U+0020, U+0085, U+200E, U+200F,
U+2028, and U+2029.
length
The number of codepoints.
string.length("héllo") // 5 length = (string : String) -> Int { list.length(core.codepoints(string)) } byte_size
The number of UTF-8 bytes.
string.byte_size("héllo") // 6 byte_size = (string : String) -> Int { core.byte_size(string) } is_empty
True for "".
is_empty = (string : String) -> Bool { string == "" } concat
The strings one after the other.
concat = (strings : List(String)) -> String { core.concat(strings) } append
to and then suffix, as a function.
append = (to : String, suffix : String) -> String { to <> suffix } join
The strings with with between every two of them.
string.join(["a", "b", "c"], ", ") // "a, b, c" join = (strings : List(String), with : String) -> String { repeat
The string times times, one after the other. "" when times is 0 or
less.
repeat = (string : String, times : Int) -> String { split
Cuts a string at every place where on is, and takes out on. With
on as "", it cuts between every two codepoints.
string.split("a,b,,c", ",") // ["a", "b", "", "c"]
string.split("abc", "") // ["a", "b", "c"] split = (string : String, on : String) -> List(String) { split_once
Cuts a string in two at the first place where on is, and takes out
on. None when on is not in the string, or is "".
string.split_once("key=value=x", "=") // Some(("key", "value=x")) split_once = (string : String, on : String) -> Option((String, String)) { lines
Cuts a string into lines, at "\n" and at "\r\n".
string.lines("a\nb\r\nc") // ["a", "b", "c"] lines = (string : String) -> List(String) { trim
The string without white space at the start and at the end.
string.trim(" hi \n") // "hi" trim = (string : String) -> String { trim_end(trim_start(string)) } trim_start
The string without white space at the start.
trim_start = (string : String) -> String { trim_end
The string without white space at the end.
trim_end = (string : String) -> String { starts_with
True when the string starts with prefix.
starts_with = (string : String, prefix : String) -> Bool { ends_with
True when the string ends with suffix.
ends_with = (string : String, suffix : String) -> Bool { contains
True when contain is somewhere in the string. Every string contains
"".
string.contains("theory", "ory") // True contains = (does : String, contain : String) -> Bool { replace
Puts with in the place of every each in the string. When each is
"", the string is the same.
string.replace("www.example.com", ".", "-") // "www-example-com" replace = (in : String, each : String, with : String) -> String { slice
length codepoints from the codepoint at at_index, counting from 0.
A negative index counts from the end: -1 is the last codepoint. The
slice stops at the end of the string. A negative length gives "".
string.slice("hello", 1, 2) // "el"
string.slice("hello", -3, 2) // "ll" slice = (string : String, at_index : Int, length : Int) -> String { drop_start
The string without its first up_to codepoints.
drop_start = (from : String, up_to : Int) -> String { drop_end
The string without its last up_to codepoints.
drop_end = (from : String, up_to : Int) -> String { first
The first codepoint, as a string, or None for "".
first = (string : String) -> Option(String) { last
The last codepoint, as a string, or None for "".
last = (string : String) -> Option(String) { pop_codepoint
The first codepoint, as a string, and the rest, or None for "".
string.pop_codepoint("abc") // Some(("a", "bc")) pop_codepoint = (string : String) -> Option((String, String)) { crop
The string from the first place where before is. When before is not
there, the string is the same.
string.crop("The Lone Ranger", "Lone") // "Lone Ranger" crop = (from : String, before : String) -> String { remove_prefix
The string without prefix at its start. When it does not start with
prefix, the string is the same.
string.remove_prefix("@lpil", "@") // "lpil" remove_prefix = (from : String, matching : String) -> String { remove_suffix
The string without suffix at its end. When it does not end with
suffix, the string is the same.
remove_suffix = (from : String, matching : String) -> String { to_upper
The string with every codepoint in upper case, by the simple uppercase
mapping of Unicode. A codepoint with no such mapping, such as ß, stays
as it is.
string.to_upper("héllo") // "HÉLLO"
string.to_upper("straße") // "STRAßE" to_upper = (string : String) -> String { core.to_upper(string) } to_lower
The string with every codepoint in lower case, by the simple lowercase mapping of Unicode.
string.to_lower("ΑΒΓ") // "αβγ" to_lower = (string : String) -> String { core.to_lower(string) } capitalise
The first codepoint in upper case and the rest in lower case.
string.capitalise("mamouna") // "Mamouna" capitalise = (string : String) -> String { reverse
The codepoints in the other order.
string.reverse("abc") // "cba" reverse = (string : String) -> String { from_reversed(core.codepoints(string)) } pad_left
Puts with, repeated, before the string until it has to codepoints.
The last copy of with may be cut. A string that is long enough stays.
string.pad_left("121", 5, ".") // "..121"
string.pad_left("121", 6, "XY") // "XYX121" pad_left = (string : String, to : Int, with : String) -> String { pad_right
Puts with, repeated, after the string until it has to codepoints.
The last copy of with may be cut. A string that is long enough stays.
pad_right = (string : String, to : Int, with : String) -> String { to_codepoints
The codepoints of the string, in order.
to_codepoints = (string : String) -> List(UtfCodepoint) { from_codepoints
The string of these codepoints.
from_codepoints = (codepoints : List(UtfCodepoint)) -> String { to_codepoint_strings
Every codepoint as a string of its own.
string.to_codepoint_strings("hé") // ["h", "é"] to_codepoint_strings = (string : String) -> List(String) { utf_codepoint
The codepoint with this number, or Error(Nil) when it is not a Unicode
scalar value (0 to 0x10FFFF, but not 0xD800 to 0xDFFF).
utf_codepoint = (value : Int) -> Result(UtfCodepoint, Nil) { utf_codepoint_to_int
The number of a codepoint.
utf_codepoint_to_int = (codepoint : UtfCodepoint) -> Int { compare
Compares two strings by their codepoints, one by one. This is also the order of their UTF-8 bytes.
string.compare("Anthony", "Anthony") // Equal
string.compare("A", "B") // Less compare = (a : String, b : String) -> Order { inspect
The text form of any value, as i source (§11.8).
string.inspect([1, 2]) // "[1, 2]"
string.inspect("a") // "\"a\"" inspect = <A>(term : A) -> String { core.inspect(term) } to_option
None for "", and Some(string) for any other string.
to_option = (string : String) -> Option(String) { at
One scalar as a string. Negative indexes count from the end; indexes outside the string, including very negative ones, give None.
at = (string : String, index : Int) -> Option(String) { index_of
Least full starting scalar index >= from; bounds must be in [0,length]. Empty find matches from. Overlaps are eligible.
index_of = (string : String, find : String, from : Int) -> Option(Int) { last_index_of
Greatest full starting scalar index <= from; the match may end after from. Empty find matches from; negative or past-end bounds give None.
last_index_of = (string : String, find : String, from : Int) -> Option(Int) { count
Left-to-right nonoverlapping matches. Empty find has count zero.
count = (string : String, find : String) -> Int { take_start
First up_to scalars, clamping the count to [0,length].
take_start = (from : String, up_to : Int) -> String { take_end
Last up_to scalars, clamping the count to [0,length].
take_end = (from : String, up_to : Int) -> String { split_once_last
Cuts at the last full separator, omitting it. Missing or empty on gives None. Separators at either end leave an empty component.
split_once_last = (string : String, on : String) -> Option((String, String)) { replace_n
Replaces the first max(0,up_to) nonoverlapping matches. Empty each is a no-op, and inserted text is never searched. Collects and concatenates once.
replace_n = (in : String, each : String, with : String, up_to : Int) -> String { split_when
Calls on once per scalar, left to right. True separates pieces; separator runs collapse and empty pieces are omitted. Errors stop traversal at once.
split_when = <E, N>( words
Splits on Pattern_White_Space, as trim does. NBSP is not a separator.
words = (string : String) -> List(String) { split_when(string, is_space) } map
Calls with once per scalar in order, producing one scalar per input.
map = <N>( filter
Calls keeping once per scalar in order. Errors stop later calls.
filter = <N>(string : String, keeping : (UtfCodepoint) <- N -> Bool) -> String { fold
Folds left to right with (accumulator,scalar); empty input gives from.
fold = <A, N>(