Thursday, 18 September 2014

Swift functions as parameters and getting Closure(s)

Previously I'd mentioned reading about closures helped me as a programmer more familiar with C-sharp to understand some of the design philosophies and put them into context. The function definition syntax in Swift is different from what I was familiar with in C-sharp/Java, but makes it's own logical sense. Continuing the journey this helps to understand what Swift closures are and how they fit into the language.

First of all, let's look at a basic function definition:

func myfunction(paramter1:String, parameter2:Int) -> (result:Int)

All, good. This boils down to the following prototype:

(String, Int) -> (Int)

Which means it is a function that takes a String and an Int and returns an Int.

Function prototypes as inputs
Now consider that this function definition itself can be a description of a parameter or return value as well:

func usingfunction( functionparameter: (String, Int) -> (Int)) -> Int

Which is saying that usingfunction is a function that takes a function as a parameter that has the prototype (String, Int) -> (Int) and returns an Int itself. It could be quite simply used by calling it:

{
  return functionparameter("parameter",1)
}

And calling using function is as simple as:

let result = usingfunction(myfunction)

Function prototypes as outputs
In the neat way in Swift that there is consistency in function input and output definitions the same can also be tried for returning a function from a function:

func returningfunction(Void) -> ( (String, Int) -> (Int) )

Great. We can now use that as follows in the implementation of returning function:

{
  return myfunction
}

And then using returningfunction:

let functionresult = returningfunction()

let result = functionresult("string",1)

Getting Closure
So, with the groundwork of passing and receiving functions and parameters we can now look at closures. Quite simply closures are the blocks of the function code above without naming the actual function. WTF? Let's take a look. In the usingfunction case let's say that rather than passing myfunction into the usingfunction we wanted to just write that code directly there as it might be a simple comparator or other operation. In that case, we define a closure. The syntax for this is as follows:

{ (inputs) -> (outputs) in statements }

Where the closure is everything in and including the curly braces. The tell here is the keyword 'in'. So we could write our previous example as:

let result = usingfunction( { ("some string", 1) -> Int in 
   // write some code here
   return 1 


Where this got a little confusing for me at first is where the syntax can be simplified in the case that some of these parts can be inferred, for example if it is obvious that the result should be returned.  We'll get onto more of that later.


No comments:

Post a Comment