Prompt
Prefer stable data-structure lookups over recomputing indices in update paths—especially when the underlying collection can reorder.
Guideline
- Avoid linear searches in hot paths: if you need an element’s position during frequent updates, don’t use patterns like
array.indexOf(x)repeatedly. Use a map (e.g.,WeakMap/Map) that gives the current index in O(1). - Preserve invariants under reordering: if you consider capturing an
indexin a subscription/callback, ensure that index remains valid after operations likesetQueries()reorder the internal list. If not, don’t capture the position—compute it via the maintained map at update time. - Add regression tests for subtle ordering/shape issues:
- Ordering: tests should cover reordering while subscriptions are active, and verify result placement after updates/invalidation.
- Aggregation semantics: when appending streamed chunks, ensure you don’t accidentally change array dimensionality (e.g., avoid implicit flattening).
Example (index stability + O(1) lookup)
// Bad: recomputes position each update (and may be O(n))
function onUpdate(observer: Observer, result: Result) {
const index = observers.indexOf(observer) // linear + fragile
if (index !== -1) results[index] = result
}
// Good: keep a maintained index map and look up at update time
const indexMap = new WeakMap<Observer, number>()
function onUpdate(observer: Observer, result: Result) {
const index = indexMap.get(observer)
if (index !== undefined) results[index] = result
}
Example (stream aggregation shape correctness)
// If TQueryFnData could itself be an array, avoid implicit flattening:
// concat(chunk) may flatten a chunk when chunk is an array.
result = prev.concat([chunk]) // keeps 1-dimensional “array of chunks” shape