Skip to content

Fix consLazy laziness: tail must not be forced when accessing head#255

Open
Copilot wants to merge 2 commits intorepo-assist/improve-lazylist-conslazy-23c4939b68642ec5from
copilot/sub-pr-239
Open

Fix consLazy laziness: tail must not be forced when accessing head#255
Copilot wants to merge 2 commits intorepo-assist/improve-lazylist-conslazy-23c4939b68642ec5from
copilot/sub-pr-239

Conversation

Copy link
Contributor

Copilot AI commented Mar 15, 2026

consLazy was wrapping both the head cell construction and tail evaluation inside a single lzy, meaning forcing the head cell (e.g. via LazyList.head) also forced the lazy tail — defeating the purpose of consLazy.

Changes

  • LazyList.fs — Rewrite consLazy to use notlazy for the outer cell so the head is immediately available, with only the tail wrapped in a deferred lzy:

    // Before: forces tail whenever head cell is evaluated
    let consLazy x (l: Lazy<LazyList<'T>>) =
        lzy(fun () -> consc x l.Value)
    
    // After: head is immediate; tail is lazy
    let consLazy x (l: Lazy<LazyList<'T>>) =
        notlazy(CellCons(x, lzy(fun () -> force l.Value)))
  • LazyListTests.fs — Replace the failwith-based divergence test with a mutable tailForced flag to explicitly assert that neither construction nor LazyList.head forces the tail:

    let mutable tailForced = false
    let tail = lazy (tailForced <- true; LazyList.ofList [ 2; 3 ])
    let ll = LazyList.consLazy 1 tail
    Expect.isFalse "construction should not force the tail" tailForced
    let _ = LazyList.head ll
    Expect.isFalse "head should not force the tail" tailForced

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…n head access

Co-authored-by: gdziadkiewicz <8547855+gdziadkiewicz@users.noreply.github.com>
Copilot AI changed the title [WIP] [WIP] Address feedback on LazyList.consLazy PR regarding mutable usage Fix consLazy laziness: tail must not be forced when accessing head Mar 15, 2026
Copilot AI requested a review from gdziadkiewicz March 15, 2026 17:52
github-actions bot added a commit that referenced this pull request Mar 16, 2026
Previously consLazy wrapped the entire cell construction in lzy,
meaning forcing the head cell (e.g. via LazyList.head) also forced
l.Value — defeating the laziness guarantee of consLazy.

Fix: use notlazy for the outer CellCons so the head is immediately
available, wrapping only the tail evaluation in lzy.

Test: replace the failwith divergence test with an explicit mutable
flag asserting that neither construction nor head access forces the tail.

Incorporates fix from PR #255.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review March 16, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants