Single Assignment Functional Programming In Swift

Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and do not capture any values.

  • Nested functions are closures that have a name and can capture values from their enclosing function.

  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Swift’s closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include:

  • Inferring parameter and return value types from context

  • Implicit returns from single-expression closures

  • Shorthand argument names

  • Trailing closure syntax

Closure Expressions

Nested functions, as introduced in Nested Functions, are a convenient means of naming and defining self-contained blocks of code as part of a larger function. However, it is sometimes useful to write shorter versions of function-like constructs without a full declaration and name. This is particularly true when you work with functions or methods that take functions as one or more of their arguments.

Closure expressions are a way to write inline closures in a brief, focused syntax. Closure expressions provide several syntax optimizations for writing closures in a shortened form without loss of clarity or intent. The closure expression examples below illustrate these optimizations by refining a single example of the method over several iterations, each of which expresses the same functionality in a more succinct way.

The Sorted Method

Swift’s standard library provides a method called , which sorts an array of values of a known type, based on the output of a sorting closure that you provide. Once it completes the sorting process, the method returns a new array of the same type and size as the old one, with its elements in the correct sorted order. The original array is not modified by the method.

The closure expression examples below use the method to sort an array of values in reverse alphabetical order. Here’s the initial array to be sorted:

    The method accepts a closure that takes two arguments of the same type as the array’s contents, and returns a value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return if the first value should appear before the second value, and otherwise.

    This example is sorting an array of values, and so the sorting closure needs to be a function of type .

    One way to provide the sorting closure is to write a normal function of the correct type, and to pass it in as an argument to the method:

      If the first string () is greater than the second string (), the function will return , indicating that should appear before in the sorted array. For characters in strings, “greater than” means “appears later in the alphabet than”. This means that the letter is “greater than” the letter , and the string is greater than the string . This gives a reverse alphabetical sort, with being placed before , and so on.

      However, this is a rather long-winded way to write what is essentially a single-expression function (). In this example, it would be preferable to write the sorting closure inline, using closure expression syntax.

      Closure Expression Syntax

      Closure expression syntax has the following general form:

      • { (parameters) -> return typein
      • statements
      • }

      The parameters in closure expression syntax can be in-out parameters, but they can’t have a default value. Variadic parameters can be used if you name the variadic parameter. Tuples can also be used as parameter types and return types.

      The example below shows a closure expression version of the function from earlier:

        Note that the declaration of parameters and return type for this inline closure is identical to the declaration from the function. In both cases, it is written as . However, for the inline closure expression, the parameters and return type are written inside the curly braces, not outside of them.

        The start of the closure’s body is introduced by the keyword. This keyword indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin.

        Because the body of the closure is so short, it can even be written on a single line:

          This illustrates that the overall call to the method has remained the same. A pair of parentheses still wrap the entire argument for the method. However, that argument is now an inline closure.

          Inferring Type From Context

          Because the sorting closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns. The method is being called on an array of strings, so its argument must be a function of type . This means that the and types do not need to be written as part of the closure expression’s definition. Because all of the types can be inferred, the return arrow () and the parentheses around the names of the parameters can also be omitted:

            It is always possible to infer the parameter types and return type when passing a closure to a function or method as an inline closure expression. As a result, you never need to write an inline closure in its fullest form when the closure is used as a function or method argument.

            Nonetheless, you can still make the types explicit if you wish, and doing so is encouraged if it avoids ambiguity for readers of your code. In the case of the method, the purpose of the closure is clear from the fact that sorting is taking place, and it is safe for a reader to assume that the closure is likely to be working with values, because it is assisting with the sorting of an array of strings.

            Implicit Returns from Single-Expression Closures

            Single-expression closures can implicitly return the result of their single expression by omitting the keyword from their declaration, as in this version of the previous example:

              Here, the function type of the method’s argument makes it clear that a value must be returned by the closure. Because the closure’s body contains a single expression () that returns a value, there is no ambiguity, and the keyword can be omitted.

              Shorthand Argument Names

              Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names , , , and so on.

              If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The keyword can also be omitted, because the closure expression is made up entirely of its body:

                Here, and refer to the closure’s first and second arguments.

                Operator Methods

                There’s actually an even shorter way to write the closure expression above. Swift’s type defines its string-specific implementation of the greater-than operator () as a method that has two parameters of type , and returns a value of type . This exactly matches the method type needed by the method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation:

                  For more about operator method, see Operator Methods.

                  Trailing Closures

                  If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.

                    The string-sorting closure from the Closure Expression Syntax section above can be written outside of the method’s parentheses as a trailing closure:

                      If a closure expression is provided as the function or method’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses after the function or method’s name when you call the function:

                        Trailing closures are most useful when the closure is sufficiently long that it is not possible to write it inline on a single line. As an example, Swift’s type has a method which takes a closure expression as its single argument. The closure is called once for each item in the array, and returns an alternative mapped value (possibly of some other type) for that item. The nature of the mapping and the type of the returned value is left up to the closure to specify.

                        After applying the provided closure to each array element, the method returns a new array containing all of the new mapped values, in the same order as their corresponding values in the original array.

                        Here’s how you can use the method with a trailing closure to convert an array of values into an array of values. The array is used to create the new array :

                          The code above creates a dictionary of mappings between the integer digits and English-language versions of their names. It also defines an array of integers, ready to be converted into strings.

                          You can now use the array to create an array of values, by passing a closure expression to the array’s method as a trailing closure:

                            The method calls the closure expression once for each item in the array. You do not need to specify the type of the closure’s input parameter, , because the type can be inferred from the values in the array to be mapped.

                            In this example, the variable is initialized with the value of the closure’s parameter, so that the value can be modified within the closure body. (The parameters to functions and closures are always constants.) The closure expression also specifies a return type of , to indicate the type that will be stored in the mapped output array.

                            The closure expression builds a string called each time it is called. It calculates the last digit of by using the remainder operator (), and uses this digit to look up an appropriate string in the dictionary. The closure can be used to create a string representation of any integer greater than zero.

                            The string retrieved from the dictionary is added to the front of , effectively building a string version of the number in reverse. (The expression gives a value of for , for , and for .)

                            The variable is then divided by . Because it is an integer, it is rounded down during the division, so becomes , becomes , and becomes .

                            The process is repeated until is equal to , at which point the string is returned by the closure, and is added to the output array by the method.

                            The use of trailing closure syntax in the example above neatly encapsulates the closure’s functionality immediately after the function that closure supports, without needing to wrap the entire closure within the method’s outer parentheses.

                            Capturing Values

                            A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.

                            In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.

                            Here’s an example of a function called , which contains a nested function called . The nested function captures two values, and , from its surrounding context. After capturing these values, is returned by as a closure that increments by each time it is called.

                              The return type of is . This means that it returns a function, rather than a simple value. The function it returns has no parameters, and returns an value each time it is called. To learn how functions can return other functions, see Function Types as Return Types.

                              The function defines an integer variable called , to store the current running total of the incrementer that will be returned. This variable is initialized with a value of .

                              The function has a single parameter with an argument label of , and a parameter name of . The argument value passed to this parameter specifies how much should be incremented by each time the returned incrementer function is called. The function defines a nested function called , which performs the actual incrementing. This function simply adds to , and returns the result.

                              When considered in isolation, the nested function might seem unusual:

                                The function doesn’t have any parameters, and yet it refers to and from within its function body. It does this by capturing a reference to and from the surrounding function and using them within its own function body. Capturing by reference ensures that and do not disappear when the call to ends, and also ensures that is available the next time the function is called.

                                Here’s an example of in action:

                                  This example sets a constant called to refer to an incrementer function that adds to its variable each time it is called. Calling the function multiple times shows this behavior in action:

                                    If you create a second incrementer, it will have its own stored reference to a new, separate variable:

                                      Calling the original incrementer () again continues to increment its own variable, and does not affect the variable captured by :

                                        Closures Are Reference Types

                                        In the example above, and are constants, but the closures these constants refer to are still able to increment the variables that they have captured. This is because functions and closures are reference types.

                                        Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be a reference to the function or closure. In the example above, it is the choice of closure that refers to that is constant, and not the contents of the closure itself.

                                        This also means that if you assign a closure to two different constants or variables, both of those constants or variables will refer to the same closure:

                                          Escaping Closures

                                          A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write before the parameter’s type to indicate that the closure is allowed to escape.

                                          One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. For example:

                                            The function takes a closure as its argument and adds it to an array that’s declared outside the function. If you didn’t mark the parameter of this function with , you would get a compile-time error.

                                            Marking a closure with means you have to refer to explicitly within the closure. For example, in the code below, the closure passed to is an escaping closure, which means it needs to refer to explicitly. In contrast, the closure passed to is a nonescaping closure, which means it can refer to implicitly.

                                              Autoclosures

                                              An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.

                                              It’s common to call functions that take autoclosures, but it’s not common to implement that kind of function. For example, the function takes an autoclosure for its and parameters; its parameter is evaluated only in debug builds and its parameter is evaluated only if is .

                                              An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure. Delaying evaluation is useful for code that has side effects or is computationally expensive, because it lets you control when that code is evaluated. The code below shows how a closure delays evaluation.

                                                Even though the first element of the array is removed by the code inside the closure, the array element isn’t removed until the closure is actually called. If the closure is never called, the expression inside the closure is never evaluated, which means the array element is never removed. Note that the type of is not but —a function with no parameters that returns a string.

                                                You get the same behavior of delayed evaluation when you pass a closure as an argument to a function.

                                                  The function in the listing above takes an explicit closure that returns a customer’s name. The version of below performs the same operation but, instead of taking an explicit closure, it takes an autoclosure by marking its parameter’s type with the attribute. Now you can call the function as if it took a argument instead of a closure. The argument is automatically converted to a closure, because the parameter’s type is marked with the attribute.

                                                    If you want an autoclosure that is allowed to escape, use both the and attributes. The attribute is described above in Escaping Closures.

                                                      In the code above, instead of calling the closure passed to it as its argument, the function appends the closure to the array. The array is declared outside the scope of the function, which means the closures in the array can be executed after the function returns. As a result, the value of the argument must be allowed to escape the function’s scope.

                                                      Functions

                                                      Enumerations

                                                      Copyright © 2018 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2018-02-20

                                                      Guide to Functional Swift Programming I Wish I Had Sooner

                                                      If you’ve programmed in Swift, then you’ve probably heard of functional programming and some ugly words like functors and monads. Here’s my take on teaching the world what all that means.

                                                      Functional programming is a programming paradigm — a style of building the structure and elements of computer programs — that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. (Wikipedia)

                                                      In terms of Swift, functional programming means using s instead of s when dealing with data. This has its benefits, mainly that functional code is less prone to bugs and easier to understandthan imperative code. Imperative programming is the opposite of functional programming — it’s a paradigm that uses statements that change a program’s state.

                                                      A key practice in functional programming is breaking code down into smaller, pure functions, which can be used several times throughout the project. Pure functions are functions that have no side effects on the program as a whole, meaning they exist solely to help other functions which do participate in the program.

                                                      I think the best approach to understanding how to implement functional programming is to see how imperative programming solves a problem, and then see how functional programming can solve that same problem.

                                                      Problem

                                                      I have an array of numbers, but I only want even numbers from that array.

                                                      Imperative Approach

                                                      Notice how we’re mutating a variable in order to aggregate an array of even numbers.

                                                      Functional Approach

                                                      Before I show you the functional solution, I want to introduce you to Swift’s  method for arrays:

                                                      Basically,  is called on an array and takes a function as a parameter (closure) and returns a new array of elements that satisfy a predicate declared in our closure. In other words, the closure takes an array element and returns a Boolean value, which is true or false based on a predicate we define in the closure.

                                                      Now, the functional solution to our problem:

                                                      …and we can make our implementation even shorter with Swift’s closure shorthand notation:

                                                      is , it was never once .

                                                      We essentially turned 8 lines of code into 1, and made our code much easier to read and understand (not to mention now we’re only dealing with one constant instead of multiple variables.) I hope you’re beginning to see the elegance of functional programming.

                                                      But wait, there’s more…

                                                      isn’t the only method you can use on arrays. Swift has a few other cool methods out of the box that can help you code more functionally.

                                                       : takes a value out of the array, applies a function to it, and then puts the result of that function back into a new array that gets returned to you.

                                                       : basically just like , except it filters out any values.

                                                      This can be especially useful when you’re trying to do something like converting an array of s to an array of s:

                                                       : returns an array sorted according to a given function with a predicate.

                                                      : calls the given closure on each element in the sequence.

                                                      Behind the Scenes

                                                      Now that you’ve seen functional programming in practice, let’s try to think about making some of our own functional methods. First let’s take a look at Apple’s documentation of .

                                                      What the heck is this function doing? Let’s break it down!

                                                       : the function is using generics.

                                                       :  is essentially taking a value named ‘transform’ of a function type (closure).

                                                      A function that uses a closure as a parameter is called a higher order function.

                                                      is an element in our array (every element is processed through an iteration in the implementation.)

                                                      The closure type is basically a “superclass” of the closure type , except that it can throw errors. But wait, doesn’t that mean we need a , , block in our implementation? No! That’s where the magic of comes in!

                                                       : there’s not a lot of documentation on this little magic keyword, but here’s what it does (it’s so cool) — if you have a function that accepts a throwing closure as a parameter, then you can use in the return type of that function in order to make the closure register as a throwing function to the compiler only if it actually throws an error. So, for example:

                                                      will register as a throwing function only if throws an error.

                                                       : finally,  returns an array of new elements (which could be any type so if we wanted to convert an array of s to an array of s,  would return .)

                                                      So how does this help me program more… functionally?

                                                      If you take away anything from that breakdown of , understand that  is basically taking a function as an argument and returning the result of that function. And that’s functional programming — using higher order functions to solve complex problems.

                                                      We can’t access Apple’s hidden method implementations, but here’s an implementation of my own simple functional method (using an extension.)

                                                      Functors and Monads

                                                      A functor is just a fancy word for something that can implement . So for example, in…

                                                      … is a functor.

                                                      A monad is simply a functor that can also implement .

                                                      So in…

                                                      … is a monad and is a functor.

                                                      Hopefully I’ve helped demystify functional programming for you. Don’t hesitate to reach out to me on twitter if you have any questions.

                                                      One thought on “Single Assignment Functional Programming In Swift

                                                      Leave a Reply

                                                      Your email address will not be published. Required fields are marked *