Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Building text

These methods observe their inputs once, receiver first, and return Result[str, AllocError]. Inputs remain unchanged on success and failure; the result outlives them. References are accepted. Length/layout overflow returns CapacityOverflow; storage exhaustion returns OutOfMemory. Only the final text needs storage, with no intermediate strings; small outputs require no heap allocation. The one exception is join over a generator, described below.

OperationBehavior
text.concat(other) or text + otherConcatenate two strings
separator.join(parts)Insert the separator between consecutive elements of an iterable of str
text.repeat(count)Repeat exact contents; count is i64; zero or negative yields empty
text[start:stop:step]Slice by scalar position, with Python’s clamping, omitted bounds, and steps
text.slice(start, stop)Forward scalar slice with required i64 bounds
text.replace(old, new)Replace all non-overlapping literal matches, left to right
text.removeprefix(prefix)Remove at most one exact prefix
text.removesuffix(suffix)Remove at most one exact suffix
text.strip()Remove Unicode White_Space at both ends
text.lstrip() / text.rstrip()Remove White_Space at the left/right end

Empty input to repeat produces empty output for any count.

Joining

join accepts every iterable whose for element is str, and joins exactly the pieces that loop would yield:

ArgumentPiecesAllocations
list[str]Elements in orderOne, for the result
set[str]Elements, in no promised orderOne, for the result
dict[str, V]Keys in insertion orderOne, for the result
strUnicode scalars, so "-".join("abc") is "a-b-c"One, for the result
Generator[str], including a generator expressionYielded valuesScratch growth plus one for the result

An empty iterable produces empty text; a single piece adds no separator. Empty pieces are retained. Other element types are rejected: write an f-string or convert with str.from to join numbers.

Collections and strings are observed, with or without &. join measures them before allocating, then copies once.

A generator is one-shot, so join consumes it as a for loop does: a named generator moves (sep.join(g)), and a reference to one is rejected. Its total size is unknown in advance. Pieces are appended to a scratch buffer whose capacity starts at the first piece’s size (at least 8 bytes) and at least doubles each time it fills. The result is then copied into exact-size text and the scratch is freed before join returns. Producing n > 8 bytes takes at most ceil(log2(n / 8)) + 2 allocations and holds less than 3n bytes at the peak. For example, four 10-byte pieces with ", " use scratch capacities of 10, 20, 40, and 80 bytes, then one 46-byte result. Each yielded piece is released once it is copied. On failure the generator stops where it is; its remaining state drops with it, and no partial text is returned. To bound the cost, collect the pieces into a list first or use std.text.join with a byte limit.

Choose by the shape of the text:

  • an f-string for a fixed number of pieces of mixed types, such as f"{host}:{port}"?. It reports AllocError, plus FormatError when a field runs a user formatting method or a spec is computed;
  • concat (or +) for two strings in an AllocError function;
  • join for any number of strings from one iterable.

slice includes start and excludes stop. Negative bounds count from the end; bounds clamp to [0, len(text)], without overflow for extreme i64 values. Reversed bounds yield empty text. ASCII bounds map directly to bytes; other text requires scanning scalar boundaries. Slice syntax text[a:b:c]? follows the same scalar positions and also accepts omitted bounds and a NonZero[i64] step; text[::-1]? reverses the scalars.

replace observes receiver, old, and new in that order. Inserted text is not searched again. An empty old string matches every scalar boundary, including both ends; on empty input it inserts new once. Empty new text removes matches. There is no count limit, regex interpretation, or normalization.

Prefix/suffix removal uses exact strings, including NUL, without repeated removal. Empty or missing patterns preserve the contents. Trimming takes no character-set argument, leaves interior text unchanged, and uses the same White_Space classification as isspace.