Skip to content

list_insert_at and list_slice builtins — the missing duals of list_remove_at and copy_into #544

Description

@InauguralPhysicist

Summary

The C-backed list mutation set has a gap on both sides:

  • list_remove_at of [list, i] exists; its dual list_insert_at of [list, i, v] (shift tail up, insert at i) does not. Reordering anything (tracks in a DAW, items in any editor) is remove-at + insert-at; today the insert half is a hand-rolled append-and-shift loop at interpreter speed.
  • copy_into of [dest, src, offset] copies into a list; there is no list_slice of [list, start, end] to copy a range out. lib/list.eigs can compose it as take of [drop of [xs, start], end - start], but that's two full copies through the interpreter, and drop copies the tail even when the slice is tiny.

Motivation (consumer: InauguralSystems/DeslanStudios)

The DAW port stores audio channels as plain lists. Clip rendering slices the trimmed sample range out of the source buffer on every cache miss (ab_slice in src/daw/audio_buf.eigs — a per-sample loop), and arr_move_track hand-rolls insert-at (ds_list_insert in src/core/util.eigs). Both are textbook C-loop shapes; in-language they dominate the profile for buffer-sized lists (a 10-second clip at 44.1 kHz is 441k elements per channel).

What to add

xs is [10, 20, 40]
list_insert_at of [xs, 2, 30]        # xs is [10, 20, 30, 40]; returns xs
list_insert_at of [xs, 0, 5]         # prepend
list_insert_at of [xs, len of xs, 99] # append (index == length is valid)

list_slice of [[1, 2, 3, 4, 5], 1, 4]   # [2, 3, 4] — new list, [start, end)
list_slice of [[1, 2], 5, 9]            # [] — clamped, never raises

Suggested contracts, following the neighbors' conventions:

  • list_insert_at: mutates and returns the list (like list_remove_at); out-of-range index clamps to [0, len] (or no-op like list_remove_at — either, as long as it's documented).
  • list_slice: returns a new list; indices clamp; start >= end gives []; negative indices count from the end like get_at/set_at (or are rejected — whichever matches the negative-index policy owners prefer).

Definition of done

  1. Both builtins in src/builtins.c + rows in docs/BUILTINS.md → Lists.
  2. Assertions: middle/ends insert, index-clamp behavior, slice bounds/clamping/empty, negative-index behavior locked either way.

Environment

  • EigenScript 0.29.0, HEAD 82ab2ae.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions