diff --git a/.jules/bolt.md b/.jules/bolt.md index 749e609..ed3edb1 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -126,3 +126,7 @@ If your candidate site already uses any of these, the issue is fixed. ## 2025-04-13 - Loop Filtering and Intermediate Allocations **Learning:** In Swift, using `.filter` before a `for` loop eagerly allocates a new intermediate array, causing unnecessary memory churn and processing overhead, especially during frequent operations like system monitoring. **Action:** Use `for ... where` clauses instead of eagerly filtering the collection prior to the loop (e.g., `for item in array where condition { ... }`). This prevents the allocation of intermediate arrays and improves efficiency. + +## 2025-05-15 - Array Materialization via sorted() on Lazy Sequences +**Learning:** `LazyFilterSequence` does not have a custom `sorted()` implementation. Calling `sorted()` on a `LazyFilterSequence` relies on the default `Sequence` extension, which completely consumes the sequence and materializes it into an array immediately. While chaining `.lazy.filter` before `.sorted()` avoids allocating a separate intermediate array just for the filtered results, `sorted()` itself forces array materialization regardless. Adding `.lazy` specifically *just* before `.sorted()` creates confusion because it suggests the sort operation itself is lazy (which is impossible, sorting requires the whole collection). The codebase considers `.lazy.filter.sorted` an anti-pattern. +**Action:** Do not propose adding `.lazy` before `.sorted()`. Ensure `.lazy` is only proposed when preceding operations that natively support lazy consumption like `.reduce`, `.count`, `.first`, `.contains`, or lazy `prefix`. diff --git a/Sources/CacheoutHelperLib/SysctlJournal.swift b/Sources/CacheoutHelperLib/SysctlJournal.swift index 07e9a53..65fe175 100644 --- a/Sources/CacheoutHelperLib/SysctlJournal.swift +++ b/Sources/CacheoutHelperLib/SysctlJournal.swift @@ -360,15 +360,13 @@ public final class SysctlJournal { /// `rollbackAll()` does not restore an intermediate value. private func revertStaleEntries() { let now = Date() - var firstStaleIndex: [String: Int] = [:] - // Identify stale, un-rolled-back entries. - for i in state.entries.indices { - guard !state.entries[i].rolledBack else { continue } + let firstStaleIndex: [String: Int] = state.entries.indices.reduce(into: [:]) { dict, i in + guard !state.entries[i].rolledBack else { return } let age = now.timeIntervalSince(state.entries[i].timestamp) - guard age > Self.maxEntryAge else { continue } - if firstStaleIndex[state.entries[i].name] == nil { - firstStaleIndex[state.entries[i].name] = i + guard age > Self.maxEntryAge else { return } + if dict[state.entries[i].name] == nil { + dict[state.entries[i].name] = i } } @@ -426,11 +424,10 @@ public final class SysctlJournal { @discardableResult private func performRollback() -> Bool { // Collect the first un-rolled-back entry per sysctl name. - var firstEntryIndex: [String: Int] = [:] - for i in state.entries.indices { - guard !state.entries[i].rolledBack else { continue } - if firstEntryIndex[state.entries[i].name] == nil { - firstEntryIndex[state.entries[i].name] = i + let firstEntryIndex: [String: Int] = state.entries.indices.reduce(into: [:]) { dict, i in + guard !state.entries[i].rolledBack else { return } + if dict[state.entries[i].name] == nil { + dict[state.entries[i].name] = i } }