Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tuple and Function Argument in Swift

Tags:

swift

tuples

In Swift, how is tuple related to function argument?

In the following two examples the function returns the same type even though one takes a tuple while the other takes two arguments. From the caller standpoint (without peeking at the code), there is no difference whether the function takes a tuple or regular arguments.

Is function argument related to tuple in some ways?

e.g.

func testFunctionUsingTuple()->(Int, String)->Void {
    func t(x:(Int, String)) {
        print("\(x.0) \(x.1)")
    }

    return t
}

func testFuncUsingArgs()->(Int, String)->Void {
    func t(x:Int, y:String) {
        print("\(x) \(y)")
    }

    return t
}

do {
    var t = testFunctionUsingTuple()
    t(1, "test")
}

do {
    var t = testFuncUsingArgs()
    t(1, "test")
}

There is also inconsistencies in behavior when declaring tuple in function argument in a regular function (rather than a returned function):

func funcUsingTuple(x:(Int, String)) {
    print("\(x.0) \(x.1)")
}

func funcUsingArgs(x:Int, _ y:String) {
    print("\(x) \(y)")
}

// No longer works, need to call funcUsingTuple((1, "test")) instead
funcUsingTuple(1, "test")   
funcUsingArgs(1, "test3")

UPDATED:

Chris Lattner's clarification on tuple:

"x.0” where x is a scalar value produces that scalar value, due to odd behavior involving excessive implicit conversions between scalars and tuples. This is a bug to be fixed.

In "let x = (y)”, x and y have the same type, because (x) is the syntax for a parenthesis (i.e., grouping) operator, not a tuple formation operator. There is no such thing as a single-element unlabeled tuple value.

In "(foo: 42)” - which is most commonly seen in argument lists - you’re producing a single element tuple with a label for the element. The compiler is currently trying hard to eliminate them and demote them to scalars, but does so inconsistently (which is also a bug). That said, single-element labeled tuples are a thing.

like image 883
Boon Avatar asked Jul 09 '15 14:07

Boon


1 Answers

Every function takes exactly one tuple containing the function's arguments. This includes functions with no arguments which take () - the empty tuple - as its one argument.

Here is how the Swift compiler translates various paren forms into internal representations:

() -> Void
(x) -> x
(x, ...) -> [Tuple x ...]

and, if there was a tuple? function, it would return true on: Void, X, [Tuple x ...].

And here is your proof:

let t0 : () = ()
t0.0 // error

let t1 : (Int) = (100)
t1.0 -> 100
t1.1 // error

let t2 : (Int, Int) = (100, 200)
t2.0 -> 100
t2.1 -> 200
t2.2 // error

[Boldly stated w/o a Swift interpreter accessible at the moment.]

From AirSpeedVelocity

But wait, you ask, what if I pass something other than a tuple in? Well, I answer (in a deeply philosophical tone), what really is a variable if not a tuple of one element? Every variable in Swift is a 1-tuple. In fact, every non-tuple variable has a .0 property that is the value of that variable.4 Open up a playground and try it. So if you pass in a non-tuple variable into TupleCollectionView, it’s legit for it to act like a collection of one. If you’re unconvinced, read that justification again in the voice of someone who sounds really confident.

Remember the 'philosophical tone' as we've reached the 'I say potato; your say potato' phase.

like image 153
GoZoner Avatar answered Oct 04 '22 07:10

GoZoner