diff --git a/StandardLibrary/Sources/Core/Collection.hylo b/StandardLibrary/Sources/Core/Collection.hylo index 64c890737..d7d9ba30d 100644 --- a/StandardLibrary/Sources/Core/Collection.hylo +++ b/StandardLibrary/Sources/Core/Collection.hylo @@ -28,6 +28,28 @@ public trait Collection { public extension Collection { + /// Returns the number of elements in `self`. + /// + /// - Complexity: O(n), where n is the number of elements in `self`. + public fun count() -> Int { + var r = 0 + for let _ in self { &r += 1 } + return r + } + + /// Returns the position of the first element of `self` satisfying `predicate`, or + /// `end_position()` if no such element exists. + /// + /// - Complexity: O(n), where n is the number of elements in `self`. + public fun first_position(where predicate: [E](Element) -> Bool) -> Position { + var i = start_position() + let j = end_position() + while (i != j) && !predicate(self[i]) { + &i = self.position(after: i) + } + return i + } + /// Returns the result of applying `combine` on an accumulator, initialized with `initial_value`, /// and each element of `self`, in order. /// @@ -63,3 +85,15 @@ public extension Collection { } } + +public extension Collection where Element: Equatable { + + /// Returns the position of the first element of `self` that is equal to `needle`, or + /// `end_position()` if no such element exists. + /// + /// - Complexity: O(n), where n is the number of elements in `self`. + public fun first_position(of needle: Element) -> Position { + first_position(where: fun (_ e) { e == needle }) + } + +} diff --git a/Tests/LibraryTests/TestCases/CollectionTests.hylo b/Tests/LibraryTests/TestCases/CollectionTests.hylo index 7fff780a7..0b24a76e2 100644 --- a/Tests/LibraryTests/TestCases/CollectionTests.hylo +++ b/Tests/LibraryTests/TestCases/CollectionTests.hylo @@ -1,5 +1,29 @@ //- compileAndRun expecting: .success +conformance Int: Collection { + + public typealias Element = Bool + public typealias Position = Int + + public fun start_position() -> Int { 0 } + public fun end_position() -> Int { Int.bit_width() } + public fun position(after p: Int) -> Int { p + 1 } + + public subscript(_ p: Int): Bool { (self & (1 << p)) != 0 } + +} + +fun test_count() { + let a = 0 + precondition(a.count() == 64) +} + +fun test_first_position() { + let a = 4 + precondition(a.first_position(where: fun (_ x) { x.copy() }) == 2) + precondition(a.first_position(of: true) == 2) +} + fun test_reduce() { var a = Array() &a.append(1) @@ -31,6 +55,8 @@ fun test_all_satisfy() { } public fun main() { + test_count() + test_first_position() test_reduce() test_contains_where() test_all_satisfy()