This PR introduces slices of lists that are available via slice notation (e.g., `xs[1...5]`). * Moved the `take` combinator and the `List` iterator producer to `Init`. * Introduced a `toTake` combinator: `it.toTake` behaves like `it`, but it has the same type as `it.take n`. There is a constant cost per iteration compared to `it` itself. * Introduced `List` slices. Their iterators are defined as `suffixList.iter.take n` for upper-bounded slices and `suffixList.iter.toTake` for unbounded ones. Performance characteristics of using the slice `list[a...b]`: * when creating it: `O(a)` * every iterator step: `O(1)` * `toList`: `O(b - a + 1)` (given that a <= b) Because the slice only stores a suffix of `xs` internally, two slices can be equal even though the underlying lists differ in an irrelevant prefix. Because the `stop` field is allowed to be beyond the list's upper bound, the slices `[1][0...1]` and `[1][0...2]` are not equal, even though they effectively cover the same range of the same list. Improving this would require us to call `List.length` when building the slice, which would iterate through the whole list.
67 lines
2.1 KiB
Text
67 lines
2.1 KiB
Text
import Std.Data.Iterators
|
|
|
|
example : #[1, 2, 3][*...*].toList = [1, 2, 3] := by native_decide
|
|
|
|
example : #[1, 2, 3][*...2].toList = [1, 2] := by native_decide
|
|
|
|
example : #[1, 2, 3][*...<2].toList = [1, 2] := by native_decide
|
|
|
|
example : #[1, 2, 3][*...=1].toList = [1, 2] := by native_decide
|
|
|
|
example : #[1, 2, 3][0<...*].toList = [2, 3] := by native_decide
|
|
|
|
example : #[1, 2, 3][0<...2].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][0<...<2].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][0<...=1].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][1...*].toList = [2, 3] := by native_decide
|
|
|
|
example : #[1, 2, 3][1...2].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][1...<2].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][1...=1].toList = [2] := by native_decide
|
|
|
|
example : #[1, 2, 3][1...<10].size = 2 := by native_decide
|
|
|
|
example : (#[1, 2, 3][1...*].take 1).toList = [2] := by native_decide
|
|
|
|
example : #[1, 1, 1][0...2].size = 2 := by native_decide
|
|
|
|
-- Verify that subarray iterators are universe polymorphic
|
|
def f (_ : Type) : Nat := 1
|
|
example : #[Nat, Int][*...1].toList.map f = [1] := by native_decide
|
|
|
|
|
|
example : [1, 2, 3][*...*].toList = [1, 2, 3] := by native_decide
|
|
|
|
example : [1, 2, 3][*...2].toList = [1, 2] := by native_decide
|
|
|
|
example : [1, 2, 3][*...<2].toList = [1, 2] := by native_decide
|
|
|
|
example : [1, 2, 3][*...=1].toList = [1, 2] := by native_decide
|
|
|
|
example : [1, 2, 3][0<...*].toList = [2, 3] := by native_decide
|
|
|
|
example : [1, 2, 3][0<...2].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][0<...<2].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][0<...=1].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][1...*].toList = [2, 3] := by native_decide
|
|
|
|
example : [1, 2, 3][1...2].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][1...<2].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][1...=1].toList = [2] := by native_decide
|
|
|
|
example : [1, 2, 3][1...<10].size = 2 := by native_decide
|
|
|
|
example : [1, 1, 1][0...2].size = 2 := by native_decide
|
|
|
|
-- Verify that list slice iterators are universe polymorphic
|
|
example : [Nat, Int][*...1].toList.map f = [1] := by native_decide
|