Str

concat : Str, Str -> Str

Concatenates two strings together.

expect "ab".concat("cd") == "abcd"
expect "hello".concat("") == "hello"
expect "".concat("") == ""
contains : Str, Str -> Bool

Determines whether or not the first Str contains the second.

expect "foobarbaz".contains("bar")
expect !"apple".contains("orange")
expect "anything".contains("")
trim : Str -> Str

Return the Str with all whitespace removed from both the beginning as well as the end.

expect "   Hello      \n\n".trim() == "Hello"
trim_start : Str -> Str

Return the Str with all whitespace removed from the beginning.

expect "   Hello      \n\n".trim_start() == "Hello      \n\n"
trim_end : Str -> Str

Return the Str with all whitespace removed from the end.

expect "   Hello      \n\n".trim_end() == "   Hello"
caseless_ascii_equals : Str, Str -> Bool

Returns True if all the ASCII characters in both strings are the same, ignoring differences in capitalization. Non-ASCII characters must all be exactly the same, including capitalization. For example:

 expect "café".caseless_ascii_equals("CAFé")

 expect !"café".caseless_ascii_equals("CAFÉ")

The first call returns True because all the ASCII characters are the same when ignoring differences in capitalization, and the only non-ASCII character (é) is the same in both strings. The second call returns False because é and É are not ASCII characters, and they are different.

This function is useful for things like command-line flags and environment variable names where you know in advance that you're dealing with a string containing only ASCII characters. It has better performance than lowercasing operations which take Unicode into account.

That said, strings received from user input can always contain non-ASCII Unicode characters, and lowercasing Unicode works differently in different languages. For example, the string "I" lowercases to "i" in English and to "ı" (a dotless i) in Turkish. These rules can also change in each Unicode release, so we have separate unicode package for Unicode capitalization that can be upgraded independently from the language's builtins.

To convert a string's ASCII characters to uppercase or lowercase, you can use Str.with_ascii_uppercased or Str.with_ascii_lowercased.

with_ascii_lowercased : Str -> Str

Returns a version of the string with all ASCII characters lowercased. Non-ASCII characters are left unmodified. For example:

expect "CALFÉ".with_ascii_lowercased() == "calfÉ"

This function is useful for things like command-line flags and environment variable names where you know in advance that you're dealing with a string containing only ASCII characters. It has better performance than lowercasing operations which take Unicode into account.

That said, strings received from user input can always contain non-ASCII Unicode characters, and lowercasing Unicode works differently in different languages. For example, the string "I" lowercases to "i" in English and to "ı" (a dotless i) in Turkish. These rules can also change in each Unicode release, so we have separate unicode package for Unicode capitalization that can be upgraded independently from the language's builtins.

To do a case-insensitive comparison of the ASCII characters in a string, you can use Str.caseless_ascii_equals.

with_ascii_uppercased : Str -> Str

Returns a version of the string with all ASCII characters uppercased. Non-ASCII characters are left unmodified. For example:

 expect "café".with_ascii_uppercased() == "CAFé"

This function is useful for things like command-line flags and environment variable names where you know in advance that you're dealing with a string containing only ASCII characters. It has better performance than uppercasing operations which take Unicode into account.

That said, strings received from user input can always contain non-ASCII Unicode characters, and uppercasing Unicode works differently in different languages. For example, the string "i" uppercases to "I" in English and to "İ" (a dotted I) in Turkish. These rules can also change in each Unicode release, so we have a separate unicode package for Unicode capitalization that can be upgraded independently from the language's builtins.

To do a case-insensitive comparison of the ASCII characters in a string, you can use Str.caseless_ascii_equals.

starts_with : Str, Str -> Bool

Check if the given Str starts with a value.

expect "ABC".starts_with("A") == Bool.True
expect "ABC".starts_with("X") == Bool.False
ends_with : Str, Str -> Bool

Check if the given Str ends with a value.

expect "ABC".ends_with("C") == Bool.True
expect "ABC".ends_with("X") == Bool.False
repeat : Str, U64 -> Str

Repeats a string the given number of times.

expect "z".repeat(3) == "zzz"
expect "na".repeat(8) == "nananananananana"

Returns "" when given "" for the string or 0 for the count.

expect "".repeat(10) == ""
expect "anything".repeat(0) == ""
with_prefix : Str, Str -> Str

Adds a prefix to the given Str.

expect "Awesome".with_prefix("Roc") == "RocAwesome"
drop_prefix : Str, Str -> Str

Drops the given prefix Str from the start of a Str If the prefix is not found, returns the original string.

expect "bar".drop_prefix("foo") == "bar"
expect "foobar".drop_prefix("foo") == "bar"
drop_prefix_caseless_ascii : Str, Str -> Try(Str, [NotFound])

Drops the given prefix from the start of a Str, comparing ASCII letters without regard to capitalization. Non-ASCII bytes must match exactly.

The returned Str is a slice of the original string. If the prefix is not found, returns Err(NotFound).

expect "Cache-Control: max-age=0".drop_prefix_caseless_ascii("cache-control") == Ok(": max-age=0")
expect "X-Api-Key".drop_prefix_caseless_ascii("x_api_key") == Err(NotFound)
drop_suffix : Str, Str -> Str

Drops the given suffix Str from the end of a Str If the suffix is not found, returns the original string.

expect "bar".drop_suffix("foo") == "bar"
expect "barfoo".drop_suffix("foo") == "bar"
find_first : Str, Str -> Try({ before : Str, after : Str }, [NotFound])

Finds the first occurrence of a delimiter in a string.

The returned strings are slices of the original string.

expect "foo: bar".find_first(":") == Ok({ before: "foo", after: " bar" })
expect "foo".find_first(":") == Err(NotFound)
count_utf8_bytes : Str -> U64

Gives the number of bytes in a Str value.

expect "Hello World".count_utf8_bytes() == 11
with_capacity : U64 -> Str

Returns a string of the specified capacity without any content.

This is like calling Str.reserve on an empty string. It's intended for building up a string incrementally, for example by calling Str.concat on it:

greeting = "Hello and welcome to Roc"
subject = "Awesome Programmer"

# Evaluates to "Hello and welcome to Roc, Awesome Programmer!"
# Note that string interpolation with "${greeting}, ${subject}!" would be preferred here,
# this is just a simple example to demonstrate `Str.with_capacity`.
hello_world =
    Str.with_capacity(45)
        .concat(greeting)
        .concat(", ")
        .concat(subject)
        .concat("!")

When the final size is known up front, Str.with_capacity guarantees that subsequent calls to Str.concat will not need to reallocate. Whether this is faster than starting from "" depends on the system allocator: many allocators can extend an existing allocation in place, making the difference small or negligible. The benefit is most pronounced when reallocation would otherwise force a full copy of the string.

If you don't know the exact capacity, passing a value larger than necessary still avoids reallocation, at the cost of using more memory than is needed.

For more details, see Str.reserve.

reserve : Str, U64 -> Str

Increase a string's capacity by at least the given number of additional bytes.

When you plan to append more bytes onto a string, Str.reserve can help avoid intermediate reallocations during a chain of Str.concat calls. Consider the following example, which does not use Str.reserve:

greeting = "Hello and welcome to Roc"
subject = "Awesome Programmer"

# Evaluates to "Hello and welcome to Roc, Awesome Programmer!"
hello_world =
    greeting
        .concat(", ")
        .concat(subject)
        .concat("!")

In this example: 1. We start with greeting, which has both a length and capacity of 24 bytes. 2. .concat(", ") sees there isn't enough capacity for 2 more bytes, so it allocates a new 26-byte buffer, copies the existing 24 bytes into it, and writes ", " at the end. The old allocation is deallocated. 3. .concat(subject) repeats the process: allocate a 44-byte buffer, copy the 26 existing bytes, write "Awesome Programmer". 4. .concat("!") repeats once more: allocate 45 bytes, copy 44, write "!".

With Str.reserve, the chain only needs one allocation up front:

greeting = "Hello and welcome to Roc"
subject = "Awesome Programmer"

hello_world =
    greeting
        .reserve(21)
        .concat(", ")
        .concat(subject)
        .concat("!")

Here, .reserve(21) ensures there is room for an additional 21 bytes (", " + "Awesome Programmer" + "!"), allocating a 45-byte buffer and copying greeting into it. The subsequent Str.concat calls all fit in that capacity and do not need to reallocate.

Whether this is actually faster depends on the system allocator: many allocators can extend an existing allocation in place, in which case the per-concat reallocation is cheap and Str.reserve makes little observable difference. The benefit is most pronounced when reallocation would otherwise force a full copy of the string.

Str.reserve is not free — when more capacity is needed, it always performs a heap allocation. Only use it when you actually expect to make use of the extra capacity.

When you don't know exactly how many bytes you'll need, choosing a value somewhat higher than necessary is usually safe; a value that's too low may force later reallocation, while a value much higher than necessary just wastes memory.

If you plan to use Str.reserve on an empty string, use Str.with_capacity instead.

release_excess_capacity : Str -> Str

Shrink the memory footprint of a str such that its capacity and length are equal. Note: This will also convert seamless slices to regular lists.

to_utf8 : Str -> List(U8)

Returns a List of the string's U8 UTF-8 code units. (To split the string into a List of smaller Str values instead of U8 values, see Str.split_on.)

expect "Roc".to_utf8() == [82, 111, 99]
expect "鹏".to_utf8() == [233, 185, 143]
expect "சி".to_utf8() == [224, 174, 154, 224, 174, 191]
expect "🐦".to_utf8() == [240, 159, 144, 166]
from_utf8_lossy : List(U8) -> Str

Converts a List of U8 UTF-8 code units to a string. Any grouping of invalid byte sequences are replaced with a single unicode replacement character '�'.

An invalid byte sequence is defined as - a 2-byte-sequence starting byte, followed by less than 1 continuation byte - a 3-byte-sequence starting byte, followed by less than 2 continuation bytes - a 4-byte-sequence starting byte, followed by less than 3 continuation bytes - an invalid codepoint from the surrogate pair block - an invalid codepoint greater than 0x110000 encoded as a 4-byte sequence - any valid codepoint encoded as an incorrect sequence, for instance a codepoint that should be a 2-byte sequence encoded as a 3- or 4-byte sequence

expect Str.from_utf8_lossy([82, 111, 99, 240, 159, 144, 166]) == "Roc🐦"
expect Str.from_utf8_lossy([82, 255, 99]) == "R�c"
expect Str.from_utf8_lossy([82, 0xED, 0xA0, 0xBD, 99]) == "R�c"
from_utf8 : List(U8) -> Try(Str, [BadUtf8({ problem : Utf8Problem, index : U64 }), ..])

Converts a List of U8 UTF-8 code units to a string.

Returns Err if the given bytes are invalid UTF-8, and returns Ok("") when given [].

expect Str.from_utf8([82, 111, 99]) == Ok("Roc")
expect Str.from_utf8([233, 185, 143]) == Ok("鹏")
expect Str.from_utf8([224, 174, 154, 224, 174, 191]) == Ok("சி")
expect Str.from_utf8([240, 159, 144, 166]) == Ok("🐦")
expect Str.from_utf8([]) == Ok("")
expect Str.from_utf8([255]).is_err()
from_quote : Str -> Try(Str, [BadQuotedBytes(Str)])

Converts a string literal to a Str.

The compiler calls this when a string literal's type is Str, passing the literal's contents after escape processing.

expect Str.from_quote("Roc") == Ok("Roc")
from_interpolation : Str, Iter((Str, Str)) -> Str

Assembles an interpolated string literal.

The compiler calls this when a string literal contains interpolations: the first argument is the literal segment before the first interpolation, and the iterator yields each interpolated value paired with the literal segment that follows it.

split_on : Str, Str -> List(Str)

Split a string around a separator.

Passing "" for the separator is not useful; it returns the original string wrapped in a List.

expect "1,2,3".split_on(",") == ["1","2","3"]
expect "1,2,3".split_on("") == ["1,2,3"]
join_with : List(Str), Str -> Str

Combines a List of strings into a single string, with a separator string in between each.

expect Str.join_with(["one", "two", "three"], ", ") == "one, two, three"
expect Str.join_with(["1", "2", "3", "4"], ".") == "1.2.3.4"
is_eq : Str, Str -> Bool

Returns True if the two strings are exactly the same.

inspect : _val -> Str

Returns a human-readable representation of a value, useful for debugging.

encode : Str, fmt -> Try(encoded, err) where { fmt.encode_str : fmt, Str -> Try(encoded, err) }

Encode a string using a format that provides encode_str

decode : src, fmt -> (Try(Str, err), src) where { fmt.decode_str : fmt, src -> (Try(Str, err), src) }

Decode a string using a format that provides decode_str

Utf8Problem

:= [InvalidStartByte, UnexpectedEndOfSequence, ExpectedContinuation, OverlongEncoding, CodepointTooLarge, EncodesSurrogateHalf]
is_eq : Utf8Problem, Utf8Problem -> Bool