diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 18495e4f..49d96889 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,7 +9,7 @@ ] }, "paket": { - "version": "7.1.5", + "version": "8.0.3", "commands": [ "paket" ] @@ -33,4 +33,4 @@ ] } } -} \ No newline at end of file +} diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 19d741fa..e469abaf 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -18,7 +18,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - dotnet: [6.0.401] + dotnet: [8.0.416] node: ['14'] runs-on: ${{ matrix.os }} diff --git a/global.json b/global.json index 44752d33..dbe5a9b2 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.401", + "version": "8.0.416", "rollForward": "minor" } -} \ No newline at end of file +} diff --git a/paket.dependencies b/paket.dependencies index e5967dc8..ecd435d9 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -1,4 +1,4 @@ -framework: netstandard2.0, net6.0 +framework: netstandard2.0, net8.0 source https://api.nuget.org/v3/index.json nuget FSharp.Core >= 4.3.4 lowest_matching:true diff --git a/src/FSharpx.Collections/Collections.fs b/src/FSharpx.Collections/Collections.fs index 079de5d0..a07ea986 100644 --- a/src/FSharpx.Collections/Collections.fs +++ b/src/FSharpx.Collections/Collections.fs @@ -78,6 +78,16 @@ module Seq = let splitAt n seq = (Seq.take n seq, Seq.skip n seq) + /// The same as Seq.skip except will return None if not enough elements to skip or count passed is < 1 + [] + let rec trySkip<'T> (count: int) (source: seq<'T>) : Option> = + if count < 1 then + None + else + match tryHeadTail source with + | None -> None + | Some(head, tail) -> if count = 1 then Some tail else trySkip (count - 1) tail + /// Splits a sequences up to the point where the predicate holds let span predicate source = (Seq.takeWhile predicate source, Seq.skipWhile predicate source) diff --git a/tests/FSharpx.Collections.Tests/SeqTests.fs b/tests/FSharpx.Collections.Tests/SeqTests.fs index 855043d4..57a2130d 100644 --- a/tests/FSharpx.Collections.Tests/SeqTests.fs +++ b/tests/FSharpx.Collections.Tests/SeqTests.fs @@ -72,6 +72,32 @@ module SeqTests = | _ -> failwith "Unreachable" } + test "If I trySkip and I don't have a head, I should return None" { Seq.empty |> Seq.trySkip 1 |> Expect.isNone "trySkip1" } + + test "If I trySkip1 a non-empty seq, I should return just tail" { + let data = [ 1; 2; 3 ] + let actual = data |> Seq.trySkip 1 + Expect.isSome "trySkip1" actual + + match actual with + | Some subSeq -> Expect.sequenceEqual "trySkip1" [ 2; 3 ] subSeq + | _ -> failwith "Unreachable" + } + + test "If I trySkip2 a non-empty seq, I should return just last" { + let data = [ 1; 2; 3 ] + let actual = data |> Seq.trySkip 2 + Expect.isSome "trySkip2" actual + + match actual with + | Some subSeq -> Expect.sequenceEqual "trySkip2" [ 3 ] subSeq + | _ -> failwith "Unreachable" + } + + test "If I trySkip2 and seq only contains 1 element, I should return None" { + seq { yield 1 } |> Seq.trySkip 2 |> Expect.isNone "trySkip2" + } + test "I should be a to split a seq at an index" { let (a, b) = Seq.splitAt 5 data Expect.sequenceEqual "splitAt" (List.toSeq [ 1.; 2.; 3.; 4.; 5. ]) a @@ -138,9 +164,11 @@ module SeqTests = test "I should get some if try to get a index inside the seq" { Seq.tryNth 2 data |> Expect.equal "tryNth" (Some(3.)) } - test "I should get none when trySkip past the end of the seq" { Seq.skipNoFail 20 data |> Expect.sequenceEqual "skipNoFail" Seq.empty } + test "I should get empty seq when skipNoFail past the end of the seq" { + Seq.skipNoFail 20 data |> Expect.sequenceEqual "skipNoFail" Seq.empty + } - test "I should get Some when trySkip" { + test "I should get Some when skipNoFail" { Seq.skipNoFail 5 data |> Expect.sequenceEqual "skipNoFail" (List.toSeq [ 6.; 7.; 8.; 9.; 10. ]) }