June 11, 2014

Swift, Operator Overloading, and Chaining Functions and Closures

Posted in iPhone development, mac development tagged , , , , , at 6:59 pm by tetontech

Swift makes it easy to overload existing or create new operators. In this post I’m going to show how to create an operator that allows functions and closures to be chained. That is, to pass the result of one function or closure call to another without embedding the second function call in the first and without storing the result of one function call and passing it to another.

Here are two simple functions that we will be playing with. There are much better ways to accomplish this simple task in Swift. I’ve only created these for use in this overloading and chaining example.

        func createMessage(an:String)->String{
            return an+" added"
        }
        func toString(an:Int)->String{
            return "\(an)"
        }
        

These functions can used together in two different traditional ways. One is to store each intermediate result in a variable and then use the variable.

        var numString = toString(5)
        var message = createMessage(numString)
        println(message)

Another way is to embed the calls inside each other.

        println(createMessage(toString(5)))

Both of these approaches are completely valid. The first makes it easier to debug individual functions and see the order in which the functions are called. The second is more succinct but can cause a loss of understanding and call ordering in those new to programming. It can also become unintelligible if there are a large number of functions embedded within each other or if the ternary, ?:, operator is included in the calls.

An infix operator, one that appears between things like the standard + operator, can be useful in this type of situations. Other languages have what they refer to as a pipeline or piping operator, |>. If we were to create such an operator in Swift the function calls would look like this.

       5|>toString|>createMessage|>println

One advantage to this approach is that the call order of the functions is maintained. Another is it is succinct. Debugging individual functions using intermediate values is not possible without breaking up  the code but the stepwise debugger could be used instead.

The code for this new operator is small. Swift makes it easy to create using generic types.

1      //accept a value (left) and use it in the function (right)
2      operator infix |> { associativity left }
3      func |> <T,U>(left: T, right: T -> U) -> U {
4          return right(left)
5      }

Let’s take a look at each portion of the code.

Line 2 declares that we are creating an operator that will be an infix rather than a prefix or suffix operator. It will be used between to things instead of before or after. The ‘+’ operator is an infix operator with which you are familiar.

After declaring the creation of an infix operator the characters used as the operator, |>, are declared and properties of the infix are listed within the {} braces. The only property declared in this example is ‘associativity left’. This means that what is on the left side should be done before what is on the right. You could also indicate an operator precedence here if you desired. I decided not to at this point. This kept the example simpler.

Line 3 declares the function that is the operation to be executed. It lists the ‘|>’ indicator characters as the function name. It then declares two generic types T and U for later use. These must be placed inside the <> characters.

The footprint of the |> function comes next. It has two parameters, left and right. The left parameter is declared to be a singular value of some yet to be determined type T. The right parameter is declared to be a function that accepts this same type T as its only parameter and returns another yet to be determined type U. The |> function is then declared to return this same type of yet to be determined Type.

In our simple example, T is set to be Int and U to be String by the compiler. This is done for this line of code only. Some other line of code could use the |> operator with a completely different set of types for T and U.

Line 4 is the body of the function. It consists of passing the left parameter into the function that is the right parameter.

One of the nice things about  Swift is that functions are just closures bound to a name. This means that we can use the new operator with closures without needing to  modify it. Since we can use closures, we are able to capture values outside of the closure scope. This way we can have multiple parameters without having to overload the new operator. Here is an example that uses closures instead of the two small functions, toString and createMessage.

        var someString = " differently";
        5|>{
            (someNumber)->String in
                return "\(someNumber)"
        }|>{
            (a:String)->String in
                return a + " added" + someString
        }|>println

In the code above, we take advantage of the value capture ability of closures. Because we can use either closures or functions with our pipeline, |>, operator we don’t have to override it to accept multiple left-side parameters. Instead, when we need multiple parameters we can capture them in a closure instead.

In another post I’ll show how to overload this operator to pass a piece of data to an array of functions.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: