RFC 069: list.repeat Helper for Fixed-Length Initialization¶
- Status: Implemented
- Created: 2026-04-17
- Author(s): Danny Meijer (@dannymeijer)
- Related:
- RFC 030 (std collections baseline)
- Issue: https://github.com/dannys-code-corner/incan/issues/385
- RFC PR: —
- Written against: v0.2
- Shipped in: v0.3.0-dev.38
Summary¶
This RFC proposes one import-free standard-library helper, list.repeat[T](value: T, count: int) -> list[T], to create fixed-length lists initialized with the same value, so authors can express intent directly without manual append loops or sentinel-map boilerplate.
Motivation¶
In current Incan code, fixed-length initialization often appears as repeated patterns like “create empty list, iterate N times, append default/sentinel value.” This is mechanically correct but noisy, harder to scan, and easy to get subtly wrong in graph and indexing code. Comprehensions reduce some noise, but the core intent is still “repeat this value N times,” and that intent deserves a dedicated API.
This is also a practical interop concern: Incan lowers to Rust, where this operation is first-class and widely used (for example, vec![-1_i64; nodes.len()]).
Python-first users are used to concise list initialization and should have an equally direct, explicit operation in Incan, without having to hand-write append loops for a common pattern. A standard helper keeps author intent clear while still matching Rust-side semantics (Clone-based element repetition).
Goals¶
- Add one canonical helper for repeated list initialization on the built-in
listsurface. - Improve readability for sentinel maps and pre-sized working buffers.
- Keep rollout lightweight by avoiding parser syntax changes.
- Make semantics explicit for count validation and element cloning.
Non-Goals¶
- This RFC does not introduce new list literal syntax (for example Rust-style
vec![x; n]sugar). - This RFC does not add capacity-only allocation APIs.
- This RFC does not change existing list comprehension semantics.
- This RFC does not introduce deep-copy semantics beyond existing
Clonebehavior. - This RFC does not define callable-driven generation such as
list.generate(count, fn(i) -> T).
Guide-level explanation¶
Use list.repeat when you want a list of length N where every element starts from the same value.
ids = list.repeat(-1, 8)
# ids == [-1, -1, -1, -1, -1, -1, -1, -1]
This is especially useful for id maps and temporary buffers:
def unmapped_ids[T](items: list[T]) -> list[int]:
return list.repeat(-1, len(items))
For non-primitive values, the helper follows normal Clone semantics and requires cloneable element types.
Reference-level explanation¶
The standard library must provide:
list.repeat[T with Clone](value: T, count: int) -> list[T]
Normative behavior:
count == 0must return an empty list.count > 0must return a list of lengthcount.- Each returned element must be clone-derived from
value. - The function must not return aliased mutable storage that would violate normal value semantics expected from cloned elements.
count < 0must raise a runtimeValueErrorwhose message identifieslist.repeat, sayscountmust be non-negative, and includes the provided count value.
Type rules:
Tmust satisfyClone.- The return type must be
list[T]with no widening.
Complexity:
- Time complexity should be linear in
count. - Space complexity should be linear in
count.
Design details¶
API location¶
The helper belongs on the built-in list surface and must be available without an import, like existing built-in collection constructors and helpers.
Why helper over syntax¶
This feature is a reusable collection operation, not a new language form. Keeping it as a helper avoids parser syntax churn and keeps behavior testable as a normal API.
Clone semantics¶
repeat should behave like repeated append(value.clone()) for each element. This keeps behavior aligned with existing trait expectations and avoids introducing custom duplication semantics.
Error behavior¶
Negative count is a caller error and should fail at runtime with ValueError instead of silently returning empty output. The diagnostic should include the bad count value because runtime inputs are often computed and a fixed message would make the failure less actionable.
Alternatives considered¶
- Add list literal repetition syntax (for example
[value; count]): rejected for now because it expands language grammar for a problem that a stdlib API can solve cleanly. - Add
std.collections.list.repeatbehind an explicit import: rejected becauselistis already the built-in user-facing list surface, and repeated initialization is a core list operation rather than a specialized collection type from RFC 030. - Keep using comprehensions (
[x for _ in range(n)]): acceptable but less direct when the intent is repeated initialization rather than transformation. - Keep explicit loops with append: most verbose and least declarative for this use-case.
- Add
list.generate(count, fn(i) -> T)in the same RFC: rejected for this RFC because generation is a callable-driven construction API with index and invocation semantics, whilerepeatis a clone/count helper.
Drawbacks¶
- Adds another API surface that overlaps with patterns already expressible via comprehensions and loops.
- Requires
Clonefor repeated values, which can reject some types that authors might expect to repeat. - Introduces one more runtime error path (
count < 0) that callers must handle in dynamic inputs.
Implementation architecture¶
Recommended implementation is a straightforward runtime helper that validates the count guard and appends value.clone() count times, with compiler/typechecker wiring only where needed to expose the import-free list.repeat surface. Tests should cover zero, positive, negative, and non-primitive cloneable values.
Layers affected¶
- Stdlib / Runtime (
incan_stdlib): add the backing repeated-list helper and runtime tests. - Typechecker / Symbol resolution: recognize
list.repeatas an import-free built-in collection helper, enforce arity andClonecompatibility, and returnlist[T]. - Lowering / Emission: lower recognized
list.repeatcalls to the runtime helper while preserving type-directed clone behavior. - LSP / Tooling: surface completion/hover docs for the new stdlib function.
- Documentation: update collections reference/how-to examples.
Implementation Plan¶
Phase 1: Spec and built-in collection surface¶
- Finalize the import-free
list.repeatcontract, negative-count diagnostic shape, and callable-generation non-goal. - Add a canonical built-in helper identity for
list.repeatthat does not requirestd.collectionsimports.
Phase 2: Typechecker and lowering¶
- Type-check
list.repeat(value, count)with exactly two arguments. - Infer
Tfromvalue, requireTto satisfyClone, requirecount: int, and returnlist[T]without widening. - Preserve enough call identity through lowering so emission does not rely on ad hoc string matching.
Phase 3: Runtime and emission¶
- Add the runtime helper that validates non-negative counts and builds the repeated list through clone-derived elements.
- Emit recognized
list.repeatcalls to the runtime helper. - Ensure the negative-count
ValueErrorincludes the provided count.
Phase 4: Tooling, docs, and release readiness¶
- Surface completion/hover docs for
list.repeat. - Update authored collection docs and examples where fixed-length initialization is taught.
- Add a release notes entry and bump the active development version.
Implementation log¶
Spec / design¶
- Resolve RFC design questions and record
list.repeatas an import-free built-in collection helper. - Exclude callable-driven
list.generatefrom this RFC.
Typechecker / symbol resolution¶
- Recognize
list.repeatwithout requiring an import. - Validate arity,
count: int, andT with Clone. - Return
list[T]without widening.
Lowering / emission¶
- Preserve recognized
list.repeatidentity through lowering. - Emit recognized calls to the runtime helper.
Stdlib / runtime¶
- Add the repeated-list runtime helper.
- Raise rich
ValueErrordiagnostics for negative counts.
Tests¶
- Add typechecker coverage for valid calls and invalid arity/count/clone-bound cases.
- Add codegen snapshot or integration coverage for zero and positive counts.
- Add runtime coverage for negative counts.
- Add non-primitive cloneable-value coverage.
Tooling / docs / release¶
- Surface LSP completion/hover docs for
list.repeat. - Update authored collection documentation/examples.
- Add release notes entry.
- Bump the active development version.
Design Decisions¶
list.repeatis an import-free helper on the built-inlistsurface. It does not live only behindstd.collections, and RFC 069 does not add a separate top-level alias.- Negative-count diagnostics should be rich: the runtime
ValueErrorincludes the providedcountvalue as well as the non-negative-count requirement. - Callable-driven list construction, such as
list.generate(count, fn(i) -> T), is a separate feature. It is not part of RFC 069 because it requires callable invocation semantics rather than clone repetition semantics.