Summary
Track a dedicated sjsonnet lazy indexed array abstraction.
The motivation is similar to what Scala LazyList gives for sequential collections: avoid building intermediate thunks or fully materialized intermediate data when a pipeline can remain lazy. Jsonnet arrays, however, need stronger indexed semantics than LazyList: cheap length, random access by index, reverse/slice/repeat/concat behavior, and predictable materialization.
This issue is for designing and implementing a Jsonnet-specific lazy indexed array layer rather than spreading ad hoc lazy/thunk logic across individual stdlib functions.
Motivation
Today many stdlib producers and consumers still exchange Array[Eval] or allocate per-element thunks such as LazyApply1. That works, but it can create large intermediate arrays of wrappers even when the next operation only indexes, folds, joins, renders, or partially consumes the data.
A dedicated lazy indexed array abstraction could make these paths explicit:
std.map / std.mapWithIndex / std.makeArray
std.slice
std.repeat
- array concat / flatten
std.foldl / std.foldr
std.join
- materialization and rendering
Design Shape
The abstraction should be closer to an indexed lazy view than to Scala LazyList:
length is O(1)
eval(i) returns an Eval without forcing where possible
value(i) forces and caches according to existing Jsonnet semantics
asLazyArray / materialization remains available for legacy consumers
- fast bulk APIs can support consumers without each one hand-writing type branches
Possible API sketches:
def foreachEvalFast(f: Eval => Unit): Unit
def copyEvalTo(out: mutable.ArrayBuilder.ofRef[Eval]): Unit
def copyStrictTo(visitor: Visitor[?, ?]): Unit
Constraints
- Preserve lazy evaluation, trace behavior, and error retry behavior.
- Preserve tailstrict boundaries.
- Avoid turning random access into prefix evaluation.
- Keep small arrays on simple JVM-friendly representations when that wins.
- Avoid deep view trees causing stack depth or branch overhead problems.
- Make materialization behavior explicit and measurable.
Candidate Implementations
- strict array wrapper
- mapped array view
- makeArray view
- slice view
- repeated view
- concat/chunked/rope view
- range/byte specialized views
Acceptance Criteria
- A small design note or PR description documents cache/error/materialization semantics.
- At least one producer/consumer pair stops allocating unnecessary intermediate thunk arrays.
- Benchmarks include both partial-indexing and full-consumption workloads.
- Tests cover laziness, error retry, trace behavior, reverse/slice/repeat composition, and materialization.
- The first implementation is small enough to review independently; larger fusion/chunked work can follow in later PRs.
Summary
Track a dedicated sjsonnet lazy indexed array abstraction.
The motivation is similar to what Scala
LazyListgives for sequential collections: avoid building intermediate thunks or fully materialized intermediate data when a pipeline can remain lazy. Jsonnet arrays, however, need stronger indexed semantics thanLazyList: cheaplength, random access by index, reverse/slice/repeat/concat behavior, and predictable materialization.This issue is for designing and implementing a Jsonnet-specific lazy indexed array layer rather than spreading ad hoc lazy/thunk logic across individual stdlib functions.
Motivation
Today many stdlib producers and consumers still exchange
Array[Eval]or allocate per-element thunks such asLazyApply1. That works, but it can create large intermediate arrays of wrappers even when the next operation only indexes, folds, joins, renders, or partially consumes the data.A dedicated lazy indexed array abstraction could make these paths explicit:
std.map/std.mapWithIndex/std.makeArraystd.slicestd.repeatstd.foldl/std.foldrstd.joinDesign Shape
The abstraction should be closer to an indexed lazy view than to Scala
LazyList:lengthis O(1)eval(i)returns anEvalwithout forcing where possiblevalue(i)forces and caches according to existing Jsonnet semanticsasLazyArray/ materialization remains available for legacy consumersPossible API sketches:
Constraints
Candidate Implementations
Acceptance Criteria