Skip to content
kata / a language workbench

Strings and bytes

Str represents Unicode text; Bin represents bytes. A one-character string is still a Str, while Char represents one Unicode scalar value.

Double-quoted strings evaluate expressions inside {...}. Single-quoted strings keep braces literal. Both process backslash escapes. Prefix either quote form with b for a byte string; interpolated values are displayed and encoded as UTF-8.

let name = "Ada"
print("hello, {name}")
print('hello, {name}')
print(b"hello, {name}")
EscapeMeaning
\n, \r, \t, \0Newline, carriage return, tab, null
\\, \', \"Literal backslash or quote
\{, \}Literal braces in an interpolated string
\xNNHex value; one raw byte in a byte string
\uNNNNFour-digit Unicode escape
\UNNNNNNNNEight-digit Unicode escape

Unicode escapes must identify valid scalar values. b'\xff' holds one byte; text encoded to UTF-8 may take more than one byte per codepoint.

text.len() counts Unicode codepoints. text.substr(start, length) selects up to length codepoints starting at the zero-based start, with nonnegative integer arguments. A slice past the end is shortened or empty. These are not grapheme-cluster operations: one displayed character can span multiple codepoints.

let word = "héllo"
print(word.len())
print(word.substr(1, 1))
print(word.to_bin().len())

text.chars() returns an Arr[Char]. Char has classification methods is_alpha, is_digit, is_upper, is_lower, case conversion methods, to_int() for its scalar value, and hash(). is_digit() specifically recognizes ASCII digits 0 through 9; is_alpha() uses Unicode alphabetic properties.

These native string methods return values; they do not replace the receiver binding. Assign the result if you want to keep a transformed string.

MethodResult
contains(text)Whether the substring occurs
starts_with(text), ends_with(text)Whether the prefix or suffix matches
trim(), trim_start(), trim_end()Text with surrounding, leading, or trailing whitespace removed
to_upper(), to_lower()Text converted to uppercase or lowercase
replace(from, to)Text with all matching substrings replaced
split(delimiter)An Arr[Str] of parts separated by the literal delimiter
let clean = " Small Steps ".trim().to_lower()
print(clean.contains("steps"))
print(clean.replace("small", "steady"))
for word in clean.split(" ") { print(word) }

Splitting is literal, not a regular-expression operation. An empty delimiter includes empty boundary parts as well as individual codepoint strings. The word-frequency tutorial shows a small explicit normalization rule.

text.to_int() parses an integer after trimming surrounding whitespace. text.to_float() parses a floating-point value. Invalid input raises a runtime error rather than returning Res; postfix ? does not catch it. text.to_bin() returns the text’s UTF-8 bytes.

print(" 42 ".to_int())
print("3.5".to_float())
print("hi".to_bin())

binary.len() counts bytes, and binary[index] returns a Byte. Bin.from_base64(text) decodes base64 text. Byte.to_int() gives the byte’s integer value; its bitwise methods include band, ior, xor, inv, shl, and shr.

let packet = b'A\xff'
print(packet.len())
print(packet[0].to_int())
print(Bin.from_base64("aGk="))

Strings, bytes, and character values also expose hash() for library hashing. Matching method names across types does not imply identical units or return types: Str.len() counts codepoints, while Bin.len() counts bytes.