Monday, December 28, 2015

Closures syntax simplification in Swift

I think the process of simplification for the closure syntax is quite interesting

This is an initial way of passing a function as an argument, sometime called a delegate function. The example is a simply multiplication of two numbers.



func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}

func multiply(op1: Double, op2: Double) -> Double {
    return op1 * op2
}
// The main calling of the method
DoSomething(multiply)


The first step that Swift makes to simplify this is to make the multiply function an inline function, a lambda or Closure. We place the code inline, use the "in" keyword and move the curly brace.

func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}

func multiply(op1: Double, op2: Double) -> Double {
    return op1 * op2
}
// The main calling of the method
DoSomething( { 
op1: Double, op2: Double) -> Double in
   return op1 * op2
}) 


But is tidied up further because Swift, like C# in this situation, is very good with type inference.  So we can remove the type declaration of the arguments and return type because it already knows them.

func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}
// The main calling of the method
DoSomething(
(op1:, op2:) -> in
    return op1 * op2
}) 

Now we can tidy this up a little, by putting the return on the same line as the declaration
, but also remove the return keyword because we are returning an expression and it knows we are going to return a Double.

func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}
// The main calling of the method
DoSomething(
(op1:, op2:) -> in op1 * op2 })


Cool. But Swift doesn't need you to name the arguments as it will use $0 and $1 for the first two args if names are not provided. So we can write:


func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}
// The main calling of the method
DoSomething(
$0 * $1 })


One last thing. The last argument can be moved outside of the parenthesis.

func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}
// The main calling of the method
DoSomething(
$0 * $1 }

Other arguments would go inside the parenthesis of DoSomething(...), but in this case there are no other args so we can remove the parenthesis entirely.

func doSomething(operation: (Double, Double) -> Double) {
    theReturnValue = operation( 2, 3)
}
// The main calling of the method
DoSomething
 $0 * $1 }

Quite interesting.





No comments:

Post a Comment