mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Revert "Revert count(where:)" (#70816)
* Revert "Revert count(where:)"
This reverts commit 779ea19a6a.
Now that SE-0220 has been re-accepted, this adds the `count(where:)`
Sequence method to the standard library.
This commit is contained in:
@@ -64,6 +64,7 @@ set(SWIFT_BENCH_MODULES
|
|||||||
single-source/ClassArrayGetter
|
single-source/ClassArrayGetter
|
||||||
single-source/CodableTest
|
single-source/CodableTest
|
||||||
single-source/Combos
|
single-source/Combos
|
||||||
|
single-source/CountAlgo
|
||||||
single-source/DataBenchmarks
|
single-source/DataBenchmarks
|
||||||
single-source/DeadArray
|
single-source/DeadArray
|
||||||
single-source/DevirtualizeProtocolComposition
|
single-source/DevirtualizeProtocolComposition
|
||||||
|
|||||||
127
benchmark/single-source/CountAlgo.swift
Normal file
127
benchmark/single-source/CountAlgo.swift
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
//===--- CountAlgo.swift --------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See https://swift.org/LICENSE.txt for license information
|
||||||
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
import TestsUtils
|
||||||
|
|
||||||
|
public let benchmarks = [
|
||||||
|
BenchmarkInfo(
|
||||||
|
name: "CountAlgoArray",
|
||||||
|
runFunction: run_CountAlgoArray,
|
||||||
|
tags: [.validation, .api]),
|
||||||
|
BenchmarkInfo(
|
||||||
|
name: "CountAlgoString",
|
||||||
|
runFunction: run_CountAlgoString,
|
||||||
|
tags: [.validation, .api],
|
||||||
|
legacyFactor: 5),
|
||||||
|
]
|
||||||
|
|
||||||
|
@inline(never)
|
||||||
|
public func run_CountAlgoArray(_ N: Int) {
|
||||||
|
for _ in 1...10*N {
|
||||||
|
CheckResults(numbers.count(where: { $0 & 4095 == 0 }) == 25)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(never)
|
||||||
|
public func run_CountAlgoString(_ N: Int) {
|
||||||
|
let vowels = Set("aeiou")
|
||||||
|
for _ in 1...N {
|
||||||
|
CheckResults(text.count(where: vowels.contains) == 2014)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let numbers = Array(0..<100_000)
|
||||||
|
|
||||||
|
let text = """
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempus
|
||||||
|
dictum tellus placerat ultrices. Proin mauris risus, eleifend a elit ut,
|
||||||
|
semper consectetur nibh. Nulla ultricies est a vehicula rhoncus. Morbi
|
||||||
|
sollicitudin efficitur est a hendrerit. Interdum et malesuada fames ac ante
|
||||||
|
ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur
|
||||||
|
adipiscing elit. Nulla facilisi. Sed euismod sagittis laoreet. Ut elementum
|
||||||
|
tempus ultrices. Donec convallis mauris at faucibus maximus.
|
||||||
|
Nullam in nunc sit amet ante tristique elementum quis ut eros. Fusce
|
||||||
|
dignissim, ante at efficitur dapibus, ex massa convallis nibh, et venenatis
|
||||||
|
leo leo sit amet nisl. Lorem ipsum dolor sit amet, consectetur adipiscing
|
||||||
|
elit. Quisque sed mi eu mi rutrum accumsan vel non massa. Nunc condimentum,
|
||||||
|
arcu eget interdum hendrerit, ipsum mi pretium felis, ut mollis erat metus
|
||||||
|
non est. Donec eu sapien id urna lobortis eleifend et eu ipsum. Mauris
|
||||||
|
purus dolor, consequat ac nulla a, vehicula sollicitudin nulla.
|
||||||
|
Phasellus a congue diam. Curabitur sed orci at sem laoreet facilisis eget
|
||||||
|
quis est. Pellentesque habitant morbi tristique senectus et netus et
|
||||||
|
malesuada fames ac turpis egestas. Maecenas justo tellus, efficitur id
|
||||||
|
velit at, mollis pellentesque mi. Vivamus maximus nibh et ipsum porttitor
|
||||||
|
facilisis. Curabitur cursus lobortis erat. Sed vitae eros et dolor feugiat
|
||||||
|
consequat. In ac massa in odio gravida dignissim. Praesent aliquam gravida
|
||||||
|
ullamcorper.
|
||||||
|
Etiam feugiat sit amet odio sed tincidunt. Duis dolor odio, posuere at
|
||||||
|
pretium sed, dignissim eu diam. Aenean eu convallis orci, vitae finibus
|
||||||
|
erat. Aliquam nec mollis tellus. Morbi luctus sed quam et vestibulum.
|
||||||
|
Praesent id diam tempus, consectetur tortor vel, auctor orci. Aliquam
|
||||||
|
congue ex eu sagittis sodales. Suspendisse non convallis nulla. Praesent
|
||||||
|
elementum semper augue, et fringilla risus ullamcorper id. Fusce eu lorem
|
||||||
|
sit amet augue fermentum tincidunt. In aliquam libero sit amet dui rhoncus,
|
||||||
|
ac scelerisque sem porttitor. Cras venenatis, nisi quis ullamcorper
|
||||||
|
dapibus, odio dolor rutrum magna, vel pellentesque sem lectus in tellus.
|
||||||
|
Proin faucibus leo iaculis nulla egestas molestie.
|
||||||
|
Phasellus vitae tortor vitae erat elementum feugiat vel vel enim. Phasellus
|
||||||
|
fringilla lacus sed venenatis dapibus. Phasellus sagittis vel neque ut
|
||||||
|
varius. Proin aliquam, lectus sit amet auctor finibus, lorem libero
|
||||||
|
pellentesque turpis, ac condimentum augue felis sit amet sem. Pellentesque
|
||||||
|
pharetra nisl nec est congue, in posuere felis maximus. In ut nulla
|
||||||
|
sodales, pharetra neque et, venenatis dui. Mauris imperdiet, arcu vel
|
||||||
|
hendrerit vehicula, elit massa consectetur purus, eu blandit nunc orci sit
|
||||||
|
amet turpis. Vestibulum ultricies id lorem id maximus. Pellentesque
|
||||||
|
feugiat, lacus et aliquet consequat, mi leo vehicula justo, dapibus dictum
|
||||||
|
mi quam convallis magna. Quisque id pulvinar dui, consequat gravida nisl.
|
||||||
|
Nam nec justo venenatis, tincidunt enim a, iaculis odio. Maecenas eget
|
||||||
|
lorem posuere, euismod nisl vel, pulvinar ex. Maecenas vitae risus ipsum.
|
||||||
|
Proin congue sem ante, sit amet sagittis odio mattis sit amet. Nullam et
|
||||||
|
nisi nulla.
|
||||||
|
Donec vel hendrerit metus. Praesent quis finibus erat. Aliquam erat
|
||||||
|
volutpat. Fusce sit amet ultricies tellus, vitae dictum dolor. Morbi auctor
|
||||||
|
dolor vel ligula pretium aliquam. Aenean lobortis vel magna vel ultricies.
|
||||||
|
Aenean porta urna vitae ornare porta. Quisque pretium dui diam, quis
|
||||||
|
iaculis odio venenatis non. Maecenas at lacus et ligula tincidunt feugiat
|
||||||
|
eu vel ipsum. Proin fermentum elit et quam tempus, eget pulvinar nisl
|
||||||
|
pharetra.
|
||||||
|
Mauris sodales tempus erat in lobortis. Duis vitae lacinia sapien.
|
||||||
|
Pellentesque vitae massa eget orci sodales aliquet. Orci varius natoque
|
||||||
|
penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce
|
||||||
|
nisi arcu, egestas vel consectetur eu, auctor et metus. In ultricies ligula
|
||||||
|
felis, vitae pellentesque dolor tempor ac. Praesent mi magna, ultrices ut
|
||||||
|
ultrices vel, sollicitudin a leo.
|
||||||
|
Nam porta, nisi in scelerisque consequat, leo lacus accumsan massa,
|
||||||
|
venenatis faucibus tellus quam eget tellus. Curabitur pulvinar, tellus ac
|
||||||
|
facilisis consectetur, lacus lacus venenatis est, eu pretium orci augue
|
||||||
|
gravida nunc. Aenean odio tellus, facilisis et finibus id, varius vitae
|
||||||
|
diam. Aenean at suscipit sem. Suspendisse porta neque at nibh semper, sit
|
||||||
|
amet suscipit libero egestas. Donec commodo vitae justo vitae laoreet.
|
||||||
|
Suspendisse dignissim erat id ante maximus porta. Curabitur hendrerit
|
||||||
|
maximus odio, et maximus felis malesuada eu. Integer dapibus finibus diam,
|
||||||
|
quis convallis metus bibendum non.
|
||||||
|
In vel vulputate nisi, non lacinia nunc. Nullam vitae ligula finibus,
|
||||||
|
varius arcu in, pellentesque ipsum. Morbi vel velit tincidunt quam cursus
|
||||||
|
lacinia non in neque. Suspendisse id feugiat nibh. Vestibulum egestas eu
|
||||||
|
leo viverra fringilla. Curabitur ultrices sollicitudin libero, non sagittis
|
||||||
|
felis consectetur id. Aenean non metus eget leo ornare porta sed in metus.
|
||||||
|
Nullam quis fermentum sapien, sit amet sodales mi. Maecenas nec purus urna.
|
||||||
|
Phasellus condimentum enim nec magna convallis, eu lacinia libero
|
||||||
|
scelerisque. Suspendisse justo libero, maximus in auctor id, euismod quis
|
||||||
|
risus. Nam eget augue diam. Ut id risus pulvinar elit consectetur varius.
|
||||||
|
Aliquam tincidunt tortor pretium feugiat tempor. Nunc nec feugiat ex.
|
||||||
|
Ut pulvinar augue eget pharetra vehicula. Phasellus malesuada tempor sem,
|
||||||
|
ut tincidunt velit convallis in. Vivamus luctus libero vitae massa tempus,
|
||||||
|
id elementum urna iaculis. Sed eleifend quis purus quis convallis. In
|
||||||
|
rhoncus interdum mollis. Pellentesque dictum euismod felis, eget lacinia
|
||||||
|
elit blandit vel. Praesent elit velit, pharetra a sodales in, cursus vitae
|
||||||
|
tortor. In vitae scelerisque tellus.
|
||||||
|
"""
|
||||||
@@ -52,6 +52,7 @@ import Chars
|
|||||||
import ClassArrayGetter
|
import ClassArrayGetter
|
||||||
import CodableTest
|
import CodableTest
|
||||||
import Combos
|
import Combos
|
||||||
|
import CountAlgo
|
||||||
import CreateObjects
|
import CreateObjects
|
||||||
import CxxSetToCollection
|
import CxxSetToCollection
|
||||||
import CxxStringConversion
|
import CxxStringConversion
|
||||||
@@ -245,6 +246,7 @@ register(CharacterRecognizer.benchmarks)
|
|||||||
register(Chars.benchmarks)
|
register(Chars.benchmarks)
|
||||||
register(CodableTest.benchmarks)
|
register(CodableTest.benchmarks)
|
||||||
register(Combos.benchmarks)
|
register(Combos.benchmarks)
|
||||||
|
register(CountAlgo.benchmarks)
|
||||||
register(ClassArrayGetter.benchmarks)
|
register(ClassArrayGetter.benchmarks)
|
||||||
register(CreateObjects.benchmarks)
|
register(CreateObjects.benchmarks)
|
||||||
register(CxxSetToCollection.benchmarks)
|
register(CxxSetToCollection.benchmarks)
|
||||||
|
|||||||
@@ -572,6 +572,48 @@ extension Sequence where Element: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// count(where:)
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension Sequence {
|
||||||
|
/// Returns the number of elements in the sequence that satisfy the given
|
||||||
|
/// predicate.
|
||||||
|
///
|
||||||
|
/// You can use this method to count the number of elements that pass a test.
|
||||||
|
/// The following example finds the number of names that are fewer than
|
||||||
|
/// five characters long:
|
||||||
|
///
|
||||||
|
/// let names = ["Jacqueline", "Ian", "Amy", "Juan", "Soroush", "Tiffany"]
|
||||||
|
/// let shortNameCount = names.count(where: { $0.count < 5 })
|
||||||
|
/// // shortNameCount == 3
|
||||||
|
///
|
||||||
|
/// To find the number of times a specific element appears in the sequence,
|
||||||
|
/// use the equal to operator (`==`) in the closure to test for a match.
|
||||||
|
///
|
||||||
|
/// let birds = ["duck", "duck", "duck", "duck", "goose"]
|
||||||
|
/// let duckCount = birds.count(where: { $0 == "duck" })
|
||||||
|
/// // duckCount == 4
|
||||||
|
///
|
||||||
|
/// The sequence must be finite.
|
||||||
|
///
|
||||||
|
/// - Parameter predicate: A closure that takes each element of the sequence
|
||||||
|
/// as its argument and returns a Boolean value indicating whether
|
||||||
|
/// the element should be included in the count.
|
||||||
|
/// - Returns: The number of elements in the sequence that satisfy the given
|
||||||
|
/// predicate.
|
||||||
|
@_alwaysEmitIntoClient
|
||||||
|
public func count<E>(
|
||||||
|
where predicate: (Element) throws(E) -> Bool
|
||||||
|
) throws(E) -> Int {
|
||||||
|
var count = 0
|
||||||
|
for e in self {
|
||||||
|
count += try predicate(e) ? 1 : 0
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// reduce()
|
// reduce()
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -172,7 +172,9 @@ func rdar21080030() {
|
|||||||
var s = "Hello"
|
var s = "Hello"
|
||||||
// https://github.com/apple/swift/issues/50141
|
// https://github.com/apple/swift/issues/50141
|
||||||
// This should be 'cannot_call_non_function_value'.
|
// This should be 'cannot_call_non_function_value'.
|
||||||
if s.count() == 0 {} // expected-error{{cannot call value of non-function type 'Int'}} {{13-15=}}
|
if s.count() == 0 {}
|
||||||
|
// expected-error@-1 {{generic parameter 'E' could not be inferred}}
|
||||||
|
// expected-error@-2 {{missing argument for parameter 'where' in call}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// <rdar://problem/21248136> QoI: problem with return type inference mis-diagnosed as invalid arguments
|
// <rdar://problem/21248136> QoI: problem with return type inference mis-diagnosed as invalid arguments
|
||||||
@@ -1534,7 +1536,8 @@ func issue63746() {
|
|||||||
|
|
||||||
func rdar86611718(list: [Int]) {
|
func rdar86611718(list: [Int]) {
|
||||||
String(list.count())
|
String(list.count())
|
||||||
// expected-error@-1 {{cannot call value of non-function type 'Int'}}
|
// expected-error@-1 {{missing argument for parameter 'where' in call}}
|
||||||
|
// expected-error@-2 {{generic parameter 'E' could not be inferred}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rdar://108977234 - failed to produce diagnostic when argument to AnyHashable parameter doesn't conform to Hashable protocol
|
// rdar://108977234 - failed to produce diagnostic when argument to AnyHashable parameter doesn't conform to Hashable protocol
|
||||||
@@ -1553,18 +1556,18 @@ func testNilCoalescingOperatorRemoveFix() {
|
|||||||
let _ = "" /* This is a comment */ ?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{13-43=}}
|
let _ = "" /* This is a comment */ ?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{13-43=}}
|
||||||
|
|
||||||
let _ = "" // This is a comment
|
let _ = "" // This is a comment
|
||||||
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1555:13-1556:10=}}
|
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1558:13-1559:10=}}
|
||||||
|
|
||||||
let _ = "" // This is a comment
|
let _ = "" // This is a comment
|
||||||
/*
|
/*
|
||||||
* The blank line below is part of the test case, do not delete it
|
* The blank line below is part of the test case, do not delete it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1558:13-1563:10=}}
|
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1561:13-1566:10=}}
|
||||||
|
|
||||||
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1566:9=}}
|
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1569:9=}}
|
||||||
"").isEmpty {}
|
"").isEmpty {}
|
||||||
|
|
||||||
if ("" // This is a comment
|
if ("" // This is a comment
|
||||||
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1568:9-1569:12=}}
|
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1571:9-1572:12=}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -628,6 +628,40 @@ SequenceTypeTests.test("allSatisfy/Predicate") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// count(where:)
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
SequenceTypeTests.test("count/Predicate") {
|
||||||
|
for test in predicateCountTests {
|
||||||
|
let s = MinimalSequence<OpaqueValue<Int>>(
|
||||||
|
elements: test.sequence.map { OpaqueValue($0) })
|
||||||
|
expectEqual(
|
||||||
|
test.expected,
|
||||||
|
s.count(where: { test.includeElement($0.value) }),
|
||||||
|
stackTrace: SourceLocStack().with(test.loc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SequenceTypeTests.test("count/Predicate/throws") {
|
||||||
|
struct E: Error, Equatable {}
|
||||||
|
|
||||||
|
// FIXME: remove `throws(E)` annotations once error type is inferred
|
||||||
|
do throws(E) {
|
||||||
|
let c = try ([] as [Int]).count(where: { (_) throws(E) in throw E() })
|
||||||
|
expectEqual(c, 0)
|
||||||
|
} catch {
|
||||||
|
expectUnreachable()
|
||||||
|
}
|
||||||
|
|
||||||
|
do throws(E) {
|
||||||
|
let c = try [1, 2, 3].count(where: { (_) throws(E) in throw E() })
|
||||||
|
expectUnreachable()
|
||||||
|
} catch {
|
||||||
|
expectEqual(error, E())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// reduce()
|
// reduce()
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
Reference in New Issue
Block a user