Swift's handling of function types


(Jens Persson) #1

IMHO Swift's handling of function types violate the principle of least
surprise.

In the example program below, are `a` and `b` really of the same function
type?

I searched but couldn't find any proposal or discussion addressing this.

// (Xcode 8 beta 6, toolchain: development snapshot 2016-08-26)

let a: (Int, Int) -> Int = { (a, b) in a + b }
let b: ((Int, Int)) -> Int = a
// So `a` can be casted to `b`'s type, OK.

print(type(of:a)) // ((Int, Int)) -> Int
print(type(of:b)) // ((Int, Int)) -> Int

// Why are they printed the same?
// I would only expect `b`'s type to look like that.
// Now it looks like both take a tuple of two Ints.

let c = a( 1, 2 ) // Can only be called this way, as expected.
let d = b((1, 2)) // Can only be called this way, as expected.
print(c) // 3, as expected.
print(d) // 3, as expected.

print(type(of:a) == type(of:b)) // true
// What? `a` clearly takes two Ints, while `b` clearly takes a
// tuple of two Ints, yet they are the same type?
// I am perplexed.


Higher order functions and function types in Swift
(Jens Persson) #2

Slava Pestov answered this question on Twitter.
He says it's a known bug and: "Right now, function types always have a
single parameter internally. Diff between a and b is lost after type check".

···

On Sat, Aug 27, 2016 at 6:28 PM, Jens Persson <jens@bitcycle.com> wrote:

IMHO Swift's handling of function types violate the principle of least
surprise.

In the example program below, are `a` and `b` really of the same function
type?

I searched but couldn't find any proposal or discussion addressing this.

// (Xcode 8 beta 6, toolchain: development snapshot 2016-08-26)

let a: (Int, Int) -> Int = { (a, b) in a + b }
let b: ((Int, Int)) -> Int = a
// So `a` can be casted to `b`'s type, OK.

print(type(of:a)) // ((Int, Int)) -> Int
print(type(of:b)) // ((Int, Int)) -> Int

// Why are they printed the same?
// I would only expect `b`'s type to look like that.
// Now it looks like both take a tuple of two Ints.

let c = a( 1, 2 ) // Can only be called this way, as expected.
let d = b((1, 2)) // Can only be called this way, as expected.
print(c) // 3, as expected.
print(d) // 3, as expected.

print(type(of:a) == type(of:b)) // true
// What? `a` clearly takes two Ints, while `b` clearly takes a
// tuple of two Ints, yet they are the same type?
// I am perplexed.


(Joe Groff) #3

This is no longer intended to be the case in Swift 3. The former has two arguments, the latter has one argument. The implementation has not fully caught up with this change, though.

-Joe

···

On Aug 27, 2016, at 9:28 AM, Jens Persson via swift-dev <swift-dev@swift.org> wrote:

IMHO Swift's handling of function types violate the principle of least surprise.

In the example program below, are `a` and `b` really of the same function type?

I searched but couldn't find any proposal or discussion addressing this.

// (Xcode 8 beta 6, toolchain: development snapshot 2016-08-26)

let a: (Int, Int) -> Int = { (a, b) in a + b }
let b: ((Int, Int)) -> Int = a
// So `a` can be casted to `b`'s type, OK.