Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/FSharpx.Collections/LazyList.fs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ module LazyList =
let consDelayed x l =
lzy(fun () -> (consc x (lzy(fun () -> (force(l()))))))

let consLazy x (l: Lazy<LazyList<'T>>) =
notlazy(CellCons(x, lzy(fun () -> force l.Value)))

let uncons(s: LazyList<'T>) = s.Uncons

let tryUncons(s: LazyList<'T>) =
Expand Down
5 changes: 5 additions & 0 deletions src/FSharpx.Collections/LazyList.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ module LazyList =
/// followed by the list returned by the given computation. The
val consDelayed: 'T -> (unit -> LazyList<'T>) -> LazyList<'T>

///O(1). Return a new list which on consumption contains the given item
/// followed by the list wrapped in the given lazy value. More efficient than
/// <c>consDelayed</c> when a <c>Lazy</c> value is already available.
val consLazy: 'T -> Lazy<LazyList<'T>> -> LazyList<'T>

///O(1). Return the list which on consumption will consist of an infinite sequence of
/// the given item
val repeat: 'T -> LazyList<'T>
Expand Down
31 changes: 31 additions & 0 deletions tests/FSharpx.Collections.Tests/LazyListTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,37 @@ module LazyList =
test "dropDiverge1" { Expect.isTrue "divergence" (let ss = LazyList.skip 1 (LazyList.consDelayed 1 diverge) in true) } (* testing for lazy divergence *)
test "dropDiverge0" { Expect.isTrue "divergence" (let ss = LazyList.skip 0 (LazyList.delayed(fun () -> failwith "errors")) in true) } (* testing for lazy divergence *)

test "consLazy head" {
let tail = lazy (LazyList.ofList [ 2; 3 ])
Expect.equal "consLazy head" 1 (LazyList.head(LazyList.consLazy 1 tail))
}

test "consLazy toList" {
let tail = lazy (LazyList.ofList [ 2; 3 ])
Expect.equal "consLazy toList" [ 1; 2; 3 ] (LazyList.toList(LazyList.consLazy 1 tail))
}

test "consLazy lazy divergence" {
// tail is not evaluated unless the tail is consumed
let mutable tailForced = false

let tail =
lazy
(tailForced <- true
LazyList.ofList [ 2; 3 ])

let ll = LazyList.consLazy 1 tail
Expect.isFalse "consLazy divergence: construction should not force the tail" tailForced
let _ = LazyList.head ll
Expect.isFalse "consLazy divergence: head should not force the tail" tailForced
}

test "consLazy infinite" {
// build ones = 1 :: 1 :: ... using consLazy
let rec ones: LazyList<int> = LazyList.consLazy 1 (lazy ones)
Expect.equal "consLazy infinite" [ 1; 1; 1; 1; 1 ] (LazyList.take 5 ones |> LazyList.toList)
}

test "takedrop" {
Expect.equal "takedrop" [ 4; 5; 6 ]
<| LazyList.toList(LazyList.take 3 (LazyList.skip 4 nats))
Expand Down
Loading