Michael Sheaver
Michael Sheaver

Reputation: 2119

Order of passed parameters in Swift

I am currently taking an iTunes U course on Swift programming, and am stuck on this code sample below:

switch operation {
    case "×": performOperation { $0 * $1 }
    case "÷": performOperation { $1 / $0 }
    default: break
}

func performOperation(operation: (Double, Double) -> Double) {
    if operandQueue.count >= 2 {
        displayValue = operation(operandQueue.removeLast(),operandQueue.removeLast())
        enter()
    }
}

My question is: how does { $0 * $1 } get passed to operation: (Double, Double) -> Double)? This code works but I just don't see how it works. The arguments being passed do not appear to be in the correct order. From how I read the declaration of performOperation, the proper order for calling it should be '*', $0, $1. I just don't see the correspondence as being in the correct order. What am I missing here?

Upvotes: 0

Views: 252

Answers (5)

vacawama
vacawama

Reputation: 154603

performOperation takes a function/closure which takes two Doubles and returns a Double. It could have been called like this:

performOperation( {(a: Double, b: Double) -> Double in return a * b } )

You can leave off the types since the called function specifies them:

performOperation( {(a, b) in return a * b } )

And you can eliminate the return since it is only one line:

performOperation( {(a, b) in a * b } )

Then you can use the default argument names $0 and $1:

performOperation( { $0 * $1 } )

Finally, you can use trailing closure syntax to eliminate the parentheses:

performOperation { $0 * $1 }

The final version is equivalent to the first. It just uses several shortcuts.

Upvotes: 3

simons
simons

Reputation: 2400

performOperation { $0 * $1 } is a simplified concise form of performOperation({(s1 : Double, s2 : Double) in return s1 * s2 }) .

Two key terms here are capture and inference. Swift is able to "capture" the values of the parameters s1 and s2 and to "infer" the type of the return value of performOperation

ETA: following through. This can be further simplified and made more concise as follows:

case "×": performOperation(*)

Since * already exists as a function which takes 2 Doubles and returns a Double. Everything else works via inference.

Upvotes: 0

Eric Aya
Eric Aya

Reputation: 70098

(Double, Double) -> Double means it's a function that takes two Doubles as arguments and returns a Double.

This function itself is the argument for performOperation.

When you call performOperation { $0 * $1 }, the {} part is the function and $0 and $1 are its two arguments: (Double, Double).

Upvotes: 0

Epic Defeater
Epic Defeater

Reputation: 2147

The reason this work is because in the closures the name of parameter 1 is $0 and the name of the second is $1. So, in the closure what it did was take those and perform some operation on them that returns a double

Upvotes: 0

sudo make install
sudo make install

Reputation: 5669

Here's the declaration of performOperation:

func performOperation(operation: (Double, Double) -> Double)

This is a function (func) called performOperation, which takes a generic function as its only argument. This function must take two doubles ((Double, Double), aka $0 and $1) and return a double (-> Double). {$0 * $1} is a function that satisfies all of these constraints.

Does that clear things up a bit?

Upvotes: 0

Related Questions