[stdlib] [SR-4005] Allow heterogenous comparisons in elementsEqual (#8045)

* [SR-4005] Allow heterogenous comparisons in elementsEqual

When a user is supplying a predicate to compare the type equivalence
isn’t required

* elementsEqualWithPredicate tests

Compares a string of a number with an integer value by using the
elementsEqualPredicate closure

* Update test expectations to use new sequence element types

* Update hardcoded test to reference sequence
This commit is contained in:
Christian Bieniak
2017-11-30 12:06:38 +11:00
committed by Ben Cohen
parent 6c4ed9c3c2
commit ec0d53f96f
4 changed files with 58 additions and 3 deletions

View File

@@ -78,6 +78,33 @@ public struct ElementsEqualTest {
} }
} }
public struct ElementsEqualWithPredicateTest {
public let expected: Bool
public let sequence: [Int]
public let other: [String]
public let predicate: (Int, String) -> Bool
public let expectedLeftoverSequence: [Int]
public let expectedLeftoverOther: [String]
public let loc: SourceLoc
public init(
_ expected: Bool, _ sequence: [Int], _ other: [String],
_ predicate: @escaping (Int, String) -> Bool,
_ expectedLeftoverSequence: [Int],
_ expectedLeftoverOther: [String],
file: String = #file, line: UInt = #line,
comment: String = ""
) {
self.expected = expected
self.sequence = sequence
self.other = other
self.predicate = predicate
self.expectedLeftoverSequence = expectedLeftoverSequence
self.expectedLeftoverOther = expectedLeftoverOther
self.loc = SourceLoc(file, line, comment: "test data" + comment)
}
}
public struct EnumerateTest { public struct EnumerateTest {
public let expected: [(Int, Int)] public let expected: [(Int, Int)]
public let sequence: [Int] public let sequence: [Int]
@@ -450,6 +477,30 @@ public let elementsEqualTests: [ElementsEqualTest] = [
ElementsEqualTest(false, [ 1, 2 ], [ 1, 2, 3, 4 ], [], [ 4 ]), ElementsEqualTest(false, [ 1, 2 ], [ 1, 2, 3, 4 ], [], [ 4 ]),
].flatMap { [ $0, $0.flip() ] } ].flatMap { [ $0, $0.flip() ] }
func elementsEqualPredicate(_ x: Int, y: String) -> Bool {
if let intVal = Int(y) {
return x == intVal
} else {
return false
}
}
public let elementsEqualWithPredicateTests: [ElementsEqualWithPredicateTest] = [
ElementsEqualWithPredicateTest(true, [], [], elementsEqualPredicate, [], []),
ElementsEqualWithPredicateTest(false, [ 1 ], [], elementsEqualPredicate, [ 1 ], []),
ElementsEqualWithPredicateTest(false, [], [ "1" ], elementsEqualPredicate, [], [ "1" ]),
ElementsEqualWithPredicateTest(false, [ 1, 2 ], [], elementsEqualPredicate, [ 1, 2 ], []),
ElementsEqualWithPredicateTest(false, [], [ "1", "2" ], elementsEqualPredicate, [], [ "1", "2" ]),
ElementsEqualWithPredicateTest(false, [ 1, 2, 3, 4 ], [ "1", "2" ], elementsEqualPredicate, [ 3, 4 ], []),
ElementsEqualWithPredicateTest(false, [ 1, 2 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], [ "3", "4" ]),
ElementsEqualWithPredicateTest(true, [ 1, 2, 3, 4 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], []),
ElementsEqualWithPredicateTest(true, [ 1, 2 ], [ "1", "2" ], elementsEqualPredicate, [], []),
]
public let enumerateTests = [ public let enumerateTests = [
EnumerateTest([], []), EnumerateTest([], []),
EnumerateTest([ (0, 10) ], [ 10 ]), EnumerateTest([ (0, 10) ], [ 10 ]),

View File

@@ -338,12 +338,14 @@ ${equivalenceExplanation}
public func elementsEqual<OtherSequence>( public func elementsEqual<OtherSequence>(
_ other: OtherSequence${"," if preds else ""} _ other: OtherSequence${"," if preds else ""}
% if preds: % if preds:
by areEquivalent: (Element, Element) throws -> Bool by areEquivalent: (Element, OtherSequence.Element) throws -> Bool
% end % end
) ${rethrows_}-> Bool ) ${rethrows_}-> Bool
where where
OtherSequence: Sequence, OtherSequence: Sequence${" {" if preds else ","}
% if not preds:
OtherSequence.Element == Element { OtherSequence.Element == Element {
% end
var iter1 = self.makeIterator() var iter1 = self.makeIterator()
var iter2 = other.makeIterator() var iter2 = other.makeIterator()

View File

@@ -170,7 +170,8 @@ func testArchetypeReplacement3 (_ a : [Int]) {
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceVar]/Super: first[#Int?#] // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceVar]/Super: first[#Int?#]
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: map({#(transform): (Int) throws -> T##(Int) throws -> T#})[' rethrows'][#[T]#] // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: map({#(transform): (Int) throws -> T##(Int) throws -> T#})[' rethrows'][#[T]#]
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: dropLast({#(n): Int#})[#ArraySlice<Int>#] // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: dropLast({#(n): Int#})[#ArraySlice<Int>#]
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: elementsEqual({#(other): Sequence#}, {#by: (Int, Int) throws -> Bool##(Int, Int) throws -> Bool#})[' rethrows'][#Bool#] // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: elementsEqual({#(other): Sequence#}, {#by: (Int, Sequence.Element) throws -> Bool##(Int, Sequence.Element) throws -> Bool#})[' rethrows'][#Bool#]; name=elementsEqual(other: Sequence, by: (Int, Sequence.Element) throws -> Bool) rethrows
// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super: elementsEqual({#(other): Sequence#})[#Bool#]; name=elementsEqual(other: Sequence)
protocol P2 { protocol P2 {

View File

@@ -328,6 +328,7 @@ Func ReversedRandomAccessCollection.index(_:offsetBy:) has return type change fr
Func ReversedRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from ReversedRandomAccessIndex<Base>? to ReversedRandomAccessCollection.Index? Func ReversedRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from ReversedRandomAccessIndex<Base>? to ReversedRandomAccessCollection.Index?
Func ReversedRandomAccessCollection.index(after:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index Func ReversedRandomAccessCollection.index(after:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
Func ReversedRandomAccessCollection.index(before:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index Func ReversedRandomAccessCollection.index(before:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
Func Sequence.elementsEqual(_:by:) has parameter 1 type change from (Self.Iterator.Element, Self.Iterator.Element) throws -> Bool to (Self.Element, OtherSequence.Element) throws -> Bool
Func Set.formSymmetricDifference(_:) has parameter 0 type change from Set<Element> to Set<Set.Element> Func Set.formSymmetricDifference(_:) has parameter 0 type change from Set<Element> to Set<Set.Element>
Func Set.index(after:) has return type change from SetIndex<Element> to Set<Element>.Index Func Set.index(after:) has return type change from SetIndex<Element> to Set<Element>.Index
Func Set.index(of:) has return type change from SetIndex<Element>? to Set<Element>.Index? Func Set.index(of:) has return type change from SetIndex<Element>? to Set<Element>.Index?