String - pannous/warp GitHub Wiki
The exposed string type is near identical to the internal string type: Both are a lightweight classes pointing to utf8 arrays, together with some meta information such as length.
Strings can be queried for their length in bytes, chars, graphemes and codepoints:
text="你好👋"
print size of text in bytes
print length of text in chars
print count codepoints in text
size, length, count and # are identical and default to graphemes (size "👍🏽" → 1);
bytes are named: text.bytes, byte count of text, byte_size(text) (decision P40).
A char is short for character, and a character is a grapheme: a letter with its marks, not a code point.
s = "שָלוֹם"
count s // 4 characters
count s.codepoints // 6 code points: each letter's vowel point is one more
One can similarly iterate over a strings bytes chars graphemes and codepoint as such:
for x in text: ... an untyped x is each character (grapheme), otherwise name the unit:
n = 0
for each byte in "你好" { n += 1 }
n // 6, three UTF-8 bytes per character
text="你好👋"
for bytes in text: print it
for chars in text: print it
for graphemes in text: print it
for codepoints in text: print it
Note that for extremely long texts, getting the different representations can become computationally expensive, but it is done only once internally.
Other built in iterator types:
for word in text: print it
for line in text: print it
custom iterators could be implemented such as:
for paragraph in text: print it
for Page in text: print it
for letter in text: print it
for syllable in word: print it
for letter in text: print it
for icon in text: print it
with the following dispatch
paragraphs of text:= split text by "<p>" // heuristics;)
that's it because for loops over any list
(here returned by plural aware property selection 'in')
Unicode data is ~1 MB. It's needed to implement all the unicode-aware string functions like strings.EqualFold()
We may get away with some smart workarounds that cover 99.99 % of the use cases
template string are those which contain dynamic content which can be evaluated ad hoc or later. Double-quoted text interpolates holes with braces or parentheses (user decision D1, 2026-10-03):
"Hello \(friend)" // canonical (Swift) form
"It took ${time - start} milliseconds" // accepted, the normalizer hints "\(time - start)"
"costs $5, not $friend" // a bare $ is text: "only the one with the curly braces must interpolate the other is text like dollar money"
A hole names a value: an unknown name in it is an error, never its own spelling.
In sql "…" and sh "…" templates $name and ${expr} are parameters, never pasted text (Footguns: injection).
Whether a string is a template is checked at construction together with the length at no additional costs.
Since unicode offers multiple quotation brackets some of them can be used for special templating behavior.
To avoid accidental interpolation use single quotes '$100' or special quotes “no $interpolation"
A Cursor is a reading position in a text, for scanners and parsers. take_while reads while a test holds,
peek shows the next character without reading it, advance reads one:
c = Cursor("ab12 cd")
c.take_while(is_letter) // ab
c.take_while(is_digit) // 12
c.skip(" ") // yes
c.looking_at("cd") // yes
c.advance() // c
c.rest() // d
skip_while(is_space) reads blanks and gives how many, at_end() tells whether all is read, and at is the index of
the next character.