Some more examples of the same issue(s):
func takesTwoIntsFn(_ twoIntsFn: (Int, Int) -> Int) {
print("twoIntsFn:", type(of: twoIntsFn))
}
func takesIntPairFn(_ intPairFn: ((Int, Int)) -> Int) {
print("intPairFn:", type(of: intPairFn))
}
func test() {
let twoIntsFn: (Int, Int) -> Int = { $0 + $1 }
let intPairFn: ((Int, Int)) -> Int = { $0.0 + $0.1 }
print(type(of: twoIntsFn)) // (Int, Int) -> Int
print(type(of: intPairFn)) // (Int, Int) -> Int (bug?)
print(type(of: twoIntsFn) == type(of: intPairFn)) // false (as expected)
takesTwoIntsFn(twoIntsFn) // (Int, Int) -> Int
takesIntPairFn(intPairFn) // (Int, Int) -> Int (bug?)
// Note that the following compiles, but I assume it shouldn't?
takesTwoIntsFn(intPairFn) // (Int, Int) -> Int (bug?)
takesIntPairFn(twoIntsFn) // (Int, Int) -> Int (bug?)
// While the following line results in an expected error:
// let a: [(Int, Int) -> Int] = [twoIntsFn, intPairFn] // ERROR: "Cannot
// convert value of type '((Int, Int)) -> Int' to expected element type
// '(Int, Int) -> Int'"
// note that the following compiles without errors:
var arrayOfTwoIntsFns = [(Int, Int) -> Int]()
arrayOfTwoIntsFns.append(twoIntsFn)
arrayOfTwoIntsFns.append(intPairFn) // (bug?)
var arrayOfIntPairFns = [((Int, Int)) -> Int]()
// arrayOfIntPairFns = arrayOfTwoIntsFns // ERROR as expected
arrayOfIntPairFns.append(arrayOfTwoIntsFns[0]) // (bug?)
arrayOfIntPairFns.append(arrayOfTwoIntsFns[1]) // (bug?)
// arrayOfIntPairFns[0] = arrayOfTwoIntsFns[0] // ERROR as expected
// arrayOfIntPairFns.append(contentsOf: arrayOfTwoIntsFns) // ERROR as
// expected but with a nonsensical error message.
}
test()
And, I think the following is a bit puzzling to think about:
func test() {
let twoIntsFn: (Int, Int) -> Int = { $0 + $1 }
let intPairFn: ((Int, Int)) -> Int = { $0.0 + $0.1 }
// Some inputs of type (Int, Int):
let inputs: [(Int, Int)] = [(1, 2), (3, 4), (5, 6)]
// Both function types can be used with this (pair) input:
print(inputs.map(twoIntsFn)) // [3, 7, 11]
print(inputs.map(intPairFn)) // [3, 7, 11]
// I guess this have to be expected behavior (unless Swift introduced
// some other way than tuples to define arg-lists), but it raises some
// questions about in what sense the two functions have the same or
// different type ...
}
// And, if (1) the above should continue to be expected behavior, is that
// really consistent with (2) treating the following (or the overloaded hmm
// in the OP) as different functions? I think 1 and 2 might be mutually
// exclusive ...
func foo<A, B, R>(_ fn: (_ arg1: A, _ arg2: B) -> R) {
print("A two-args-function!")
}
func foo<A, B, R>(_ fn: (_ pair: (A, B)) -> R) {
print("A one-pair-arg-function!")
}
test()
(I get the same result with default toolchain of Xcode 10.1 (10B61) and dev snapshot 2018-12-06.)
This area of Swift, ie essentially the whole conflation-of-parentheses-complexity-of-problems, including single-element tuples etc, has been broken in various different ways for years.
Any chance of these things ever getting fixed, or is it too complex and too late? (serious question)
Can anything be said about the priority/severity, relation to ABI stability and future language features, etc?