visit our site

Composing functions in Swift

In Development, iOS, Mac OSX, Mobile, Swift

by Artur Termenji by June 17, 2014

In Swift – the new programming language introduced by Apple – functions are first class citizens. This basically means, that a function can be passed as a parameter, returned from another function or assigned to a value. It allows us to do a lot of useful stuff with them.

Function decorators

Let’s use the concepts of function as a first class citizen to implement some basic function decorator.

Assign functions to variables

Functions can be passed as parameters to other functions

Functions can return other functions

This concept allows us to implement function decorators in Swift.

Function decorators work as wrappers to existing functions, modifying the behavior of the code before and after a target function, without the need to modify the function itself. They augment the original functionality, thus decorate it.

Using the concepts above let’s write a simple decorator that wraps the String output of another function by some html tag.

We wrote a function that takes another function as an argument, generates a new function, augmenting the work of the original function, and returns the generated function so we can use it anywhere. Decorating function also allows us to insert some behaviour before/after function call or combine multiple functions into one.

In the example above we had to explicitly specify the signature of the function to decorate: func bold(function: String -> String). We’ve implemented bold decorator so that it decorates a function from one String value, which returns another String value. But what if one would like to create bold decorator which accepts functions with different signatures?

Abstract Functor

Let’s define an abstract Functor class. By ‘Functor’ let’s assume a class, which wraps any function and allows to call that function.

This class allows us to wrap any function and call it somewhere:

Using the Functor class we can now rewrite bold decorator to accept functions with different number of parameters:

Composing functions

Another interesting approach of using function decorators is composing several functions into single one.

Swift allows overloading basic operators. Let’s try to overload + operator to accept two functions and compose them into one function.

Above you can see two overloads of + operator which accept functors of different types and combine them into a single function.
The first overloaded version runs a Void -> Void function before main function, and the second one runs main function,
then passes its result to another T2 -> Void function and returns the result of the main function.

Let’s write an example of using this approach:

We could also implement + operator overload for plain functions, not for Functor type, but overloading operators for basic types may be a bad practice.

Another approach of composing functions may be implemented with some helper classes and without overloading operators. As an example of doing this
take a look at Before and After classes here. They allow us to compose functions in another way:

Retry/repeat function call

One another way of using function decorators and Functor class, implemented above, is to write Repeat and Retry decorators. It will allow to run a single function multiple times or until some condition is met.

Code above allows us to implement multiple calling of a function mechanism like this:

Or we can run a function until some condition is met or until we have performed some number of tries:

Conclusion

This article demonstrates a basic approach of decorating and composing functions in Swift. It is pretty easy to implement Decorator pattern in Swift and many useful decorators may be implemented using the described approach.

Having functions as first class citizens may allow creating clean, short and extensible code, which will be pretty easy to understand.

All the code examples for this article could be found in this repository.

Share
* Railsware is a premium software development consulting company, focused on delivering great web and mobile applications. Learn more about us.
  • Pingback: primer número | A coffee with VinSol()

  • KiranDev

    Easy way to shoot yourself in the foot.

    • Artur Termenji

      this method does not introduce any metaprogramming, so I don’t know how this can hurt your code.
      Anyway, this is just some kind of a playground and a proof of concept, not something that should be used in production

    • Artur Termenji

      this method does not introduce any metaprogramming, so I don’t know how this can hurt your code.
      Anyway, this is just some kind of a playground and a proof of concept, not something that should be used in production

    • griotspeak

      Care to unpack that thought?

  • WeHeartSwift

    One the best articles I have seen so far! #swift

  • Pingback: One month of Swift » We ❤ Swift()

  • IanKay

    Annoyingly this does not seem to work when parsing a function from a protocol :
    “Partial application of protocol method is not allowed”

    • IanKay

      Actually this can be achieved with protocols by wrapping it in a closure i.e.:

      //doesn’t work
      F(protocol.function).retry(param1, param2, ..)

      //works
      F({ p1, p2 in protocol.function(p1, p2) }).retry(param1, param2, …)

      A little redundant and verbose but hopefully this helps someone

  • Pingback: Crash Course | swiftioscodetutorial()

Signup for our weekly newsletter

Want to get more of Railsware blog?

RSS Feed

We're always ready to help!

Contact us