Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Swift Functional Programming - Second Edition
Swift Functional Programming - Second Edition

Swift Functional Programming: Ease the creation, testing, and maintenance of Swift codes, Second Edition

By Dr. Fatih Nayebi
$39.99 $27.98
Book Apr 2017 316 pages 2nd Edition
eBook
$39.99 $27.98
Print
$48.99
Subscription
$15.99 Monthly
eBook
$39.99 $27.98
Print
$48.99
Subscription
$15.99 Monthly

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Apr 26, 2017
Length 316 pages
Edition : 2nd Edition
Language : English
ISBN-13 : 9781787284500
Vendor :
Apple
Category :
Table of content icon View table of contents Preview book icon Preview Book

Swift Functional Programming - Second Edition

Chapter 1. Getting Started with Functional Programming in Swift

Getting onto the functional programming bandwagon needs a mindset shift, and changing our mindset is not an easy task as it takes a considerable amount of time to master a paradigm such as object-oriented programming. It needs a thorough approach, but it should also be easy to grasp. That is why we will be introduced to functional programming paradigms first, before going through each topic in detail.

This chapter introduces immutability, pattern matching, closures, as well as pure, first-class, and higher-order functions with Swift. Although all the topics in this chapter will be covered in detail in upcoming chapters, it is going to be helpful to have a broad view of the paradigms. In addition, this chapter will introduce Swift, as it is important to know the basics of the language to utilize in functional programming.

The following topics will be covered, along with examples:

  • Why functional programming matters
  • What is FP?
  • Swift language basics
  • Immutability
  • First-class, higher-order, and pure functions
  • Optionals and pattern matching
  • Closures
  • Type aliasing

Why functional programming matters


Software solutions are becoming complex, and it is necessary to structure them very well for future maintenance and extension. Software engineers try to modularize software into smaller pieces and abstract away complexities in different pieces and layers. Dividing the code into smaller pieces makes it possible to tackle each problem individually. This approach improves collaboration because different engineers can take responsibility for different pieces. Also, they can work on specific parts of the software without being concerned about the other parts.

Dividing software into smaller pieces is not the biggest challenge in most projects and programming languages. For instance, in object-oriented programming (OOP), software is divided into smaller pieces such as packages, classes, interfaces, and methods. Engineers tend to divide the software into these building blocks by domains, logic, and layers. Classes are recipes to create instances and objects. As the name suggests, the most important building blocks in OOP are objects. Engineers deal with objects, and the role and responsibility of them should be clear and understandable.

In OOP, connecting the building blocks to each other is not as easy as dividing them. Connection between different objects may propose strong coupling between them. Coupling is the biggest source of complexity in OOP. A change in a module or class could force change in all coupled modules and classes. Also, a particular module or class might be harder to reuse and test because of coupled modules or classes.

Software engineers try to loosen coupling by structuring the software well and applying different principles and design patterns. For instance, single responsibility, open-closed, Liskov substitution, and interface segregation and dependency inversion (SOLID) principles, when applied together properly, tend to make software easy to maintain and extend.

Even though it is possible to decrease the coupling and simplify software structures, managing the memory, referencing to instances, and testing of different objects remains difficult because, in OOP, objects are open to change and mutation.

In Functional Programming (FP), pure functions are the most important building blocks. Pure functions do not rely on data outside of themselves and they do not change data that exists outside of them; in other words, they do not have side effects. Pure functions are easy to test because they will always provide the same results.

Pure functions can be executed on different threads or cores without any mechanisms to handle multithreading and multiprocessing. This is a very important benefit of FP over OOP, as multicore programming mechanisms are very complex to handle in OOP. Also, programming for multicore computers is becoming more important day by day because hardware engineers have finally hit the limit of the speed of light. Computer clocks will not be getting faster in the near future, so in order to have more cycles per second, hardware engineers are adding more processors to chips. There seems to be no end to how many processors we will have in our computers. A larger number of processors to be used for a program means a more complex multithreading and multicore mechanism to handle it. FP eliminates the need for a complex multicore programming mechanism as pure functions are not dependent on any instances or data outside of themselves. It is easy to change pure functions without changing other parts of the software.

FP embraces immutability and stateless programming, and makes applications easy to maintain and extend, as managing states and tracking mutation in code is not a trivial task. In fact, Facebook, in the documentation of immutable.js, a framework that brings immutable data structures to JavaScript, states that "Much of what makes application development difficult is tracking mutation and maintaining state."

FP is a declarative programming style, so functionally written code declares the operations, expressions, and what needs to be done. Declarations are easy to trace and less verbose as, opposed to imperative programming, which sends orders to the compiler, it is verbose and hard to trace. Embracing immutability and being declarative makes applications easier to maintain and extend. We will look into examples of declarative versus imperative programming later in this chapter.

What is FP?


We know FP matters, but what is it really? There are a lot of discussions related to FP superiority and different definitions of it, but simply, it is a style of programming that models computations as the evaluation of expressions or declarations. FP is a declarative programming style, as opposed to OOP, which is categorized as imperative programming.

Theoretically, FP employs the concepts of category theory, which is a branch of mathematics. It is not necessary to know the category theory to be able to program functionally, but studying it will help to grasp some of the more advanced concepts, such as Functors, Applicative Functors, and Monads. We will get into category theory and its relationship with FP later, so for now, we are not going to talk math and we will scratch the surface of FP pragmatically.

Let's start with an example to understand the differences between imperative and declarative programming styles. The following example gives two different approaches to array-element multiplication:

let numbers = [9, 29, 19, 79] 

// Imperative example 
var tripledNumbers: [Int] = [] 
for number in numbers { 
    tripledNumbers.append(number * 3) 
} 
print(tripledNumbers) 

// Declarative example 
let tripledIntNumbers = numbers.map({ number in number * 3 }) 
print(tripledIntNumbers) 

In the imperative example, we create a mutable array of integers. Then, we give a command to go through all items in the array, multiply each item by 3, and add it to our mutable array. Basically, we order the compiler to follow specific steps. As it is written in an imperative style, when we read it, we will need to trace and follow the same steps, like a compiler, which is not very intuitive.

In the declarative example, we declare how numbers should be mapped, multiplying each number by 3. It may not look that intuitive right away if we do not know the map function and closures, but for now we need to understand the differences between commanding and declaration. This example may not be enough to grasp it. Also, understanding a concept is one thing and applying it is another. That is why we will have more examples in upcoming sections and chapters. In fact, everything in this book will be written declaratively, so we will utilize the concept intuitively.

In FP, functions are the fundamental building blocks, so programs are structured by functions. In OOP, programs are composed of classes and objects. This is a fundamental difference because, in OOP, statements can mutate the state of objects when executed, as opposed to FP, which avoids using mutable states.

FP promises that avoiding mutable states makes it easier to test, read, and understand the code. Although it is a well-known fact that state management is hard and error-prone, it is not easy to avoid mutable states in some cases, such as cocoa development and file and database operations. For now, we consider traditional OOP and FP, and we will get into the comparison and combination of different paradigms in an upcoming chapter.

FP requires functions to be first class. First-class functions are going to be treated like any other values, and can be passed to other functions or returned as a result of a function.

FP requires functions to be able to be formed as higher-order functions that take other functions as their arguments. Higher-order functions can be used to refactor code, reduce the amount of repetition, and to implement domain-specific languages (DSL).

DSLs are languages that are specialized for a particular application domain. Domain-Specific Languages, a book by Martin Fowler, is a great reference for the curious. For more curious readers, declarative Auto Layout DSLs for Swift such as SnapKit and Carthography and a talk given by Rahul Malik at Functional Swift conference on writing domain specific languages (https://github.com/rahul-malik/writing-dsls) are great resources.

FP requires functions to be pure so they do not depend on any data outside of themselves and do not change any data outside of themselves. Pure functions provide the same result each time they are executed. This property of pure functions is called referential transparency, and makes it possible to conduct equational reasoning on the code.

Equational reasoning is a way to reason about our code. It enables us to replace code blocks with others without worrying about evaluation order or state. In OOP, generally, the value of a code block depends on object context or state. Having a context and depending on state prevents replacing a code block by another, and therefore makes it impossible to conduct equational reasoning.

First-class, higher-order, and pure functions empower us to compose our applications with functions instead of using classes and objects as building blocks.

In FP, expressions can be evaluated lazily. For instance, in the following code example, only the first element in the array is evaluated:

let oneToFour = [1, 2, 3, 4] 
let firstNumber = oneToFour.lazy.map({ $0 * 3}).first! 
print(firstNumber) // The result is going to be 3 

The lazy keyword is used to get a lazy version of the collection. lazy is declared in Swift's Standard Library as a view onto the collection that provides lazy implementations of normally eager operations, such as map and filter. In this example, only the first item in the array is multiplied by 3 and the rest of the items are not mapped.

At this point, we should have a very broad view of FP concepts. To be able to get into the detail of these concepts, we will need to cover some of the Swift language basics, which are provided in the following section.

The Swift programming language


Swift is an open-source programming language developed by Apple that combines OOP and protocol-oriented programming (POP) with FP paradigms. Swift is not a pure FP language such as Haskell, Clojure, or F#, but it provides tools that facilitate FP. Swift can be used along with Objective-C to develop macOS, iOS, tvOS, and watchOS applications. Swift can also be used on Ubuntu Linux to develop web applications. This book explains Swift 3.1 and utilizes Xcode 8.3.2 compatible source code at a GitHub (https://github.com/PacktPublishing/Swift-Functional-Programming) repository, which will be updated frequently to catch up with changes to Swift.

Swift features

Swift has borrowed many concepts from other programming languages, such as Scala, Haskell, C#, Rust, and Objective-C, and has the following features.

Modern syntax

Swift has a modern syntax that eliminates the verbosity of programming languages such as Objective-C. For instance, the following code example shows an Objective-C class with a property and method. Objective-C classes are defined in two separate files (interface and implementation). The VerboseClass.h file defines an interface as a subclass of the NSObject class. It defines a property, ourArray, and a method, aMethod.

The implementation file imports the header class and provides an implementation for aMethod, as shown in the following code:

//  VerboseClass.h 
@interface VerboseClass: NSObject 
@property (nonatomic, strong) NSMutableArray *ourArray; 
- (void)aMethod:(NSMutableArray*)anArray; 
@end 

//  VerboseClass.m 
#import "VerboseClass.h" 

@implementation VerboseClass 
- (void)aMethod:(NSMutableArray*)anArray { 
    self.ourArray = [[NSMutableArrayalloc] initWithArray: @[@"One",      
    @"Two", @"Three"]]; 
} 

A similar functionality in Swift can be achieved as follows:

class ASwiftClass { 
    var ourArray: [String] = [] 

    func aMethod(anArray: [String]) { 
        self.ourArray  = anArray 
    } 
} 

let aSwiftClassInstance = ASwiftClass() 
aSwiftClassInstance.aMethod(anArray: ["one", "Two", "Three"]) 
print(aSwiftClassInstance.ourArray) 

As seen from this example, Swift eliminates a lot of unnecessary syntax and keeps code very clean and readable.

Type safety and type inference

Swift has a strong emphasis on types. Classes, enums, structs, protocols, functions, and closures can become types and be used in program composition.

Swift is a type-safe language, unlike languages such as Ruby and JavaScript. As opposed to type-variant collections in Objective-C, Swift provides type-safe collections. Swift automatically deducts types by the type-inference mechanism, a mechanism that is present in languages such as C# and C++ 11. For instance, constString in the following example is inferred as String during compile time, and it is not necessary to annotate the type:

let constString = "This is a string constant" 

Immutability

Swift makes it easy to define immutable values--in other words, constants--and empowers FP, as immutability is one of the key concepts in FP. Once constants are initialized, they cannot be altered or mutated. Although it is possible to achieve immutability in languages such as Java, it is not as easy as Swift. To define any immutable type in Swift, the let keyword can be used no matter if it is a custom type, collection type, or a Struct/enum type.

Stateless programming

Swift provides very powerful structures and enumerations that are passed by values and can be stateless, and, therefore, very efficient. Stateless programming simplifies the concurrency and multithreading, as pointed out in previous sections of this chapter.

First-class functions

Functions are first-class types in Swift, just as in languages such as Ruby, JavaScript, and Go, and can be stored, passed, and returned. First-class functions empower the FP style in Swift.

Higher-order functions

Higher-order functions can receive other functions as their parameters. Swift provides higher-order functions such as map, filter, and reduce. Also, in Swift, we can develop our own higher-order functions and DSLs.

Closures

Closures are blocks of codes that can be passed around. Closures capture the constants and variables of the context in which they are defined. Swift provides closures with a simpler syntax than Objective-C blocks.

Subscripts

Swift provides subscripts that are shortcuts to access members of collections, lists, sequences, or custom types. Subscripts can be used to set and get values by an index without needing separate methods for the setting and getting.

Pattern matching

Pattern matching is the ability to de-structure values and match different switch cases based on correct value matches. Pattern matching capabilities exist in languages such as Scala, Erlang, and Haskell. Swift provides powerful switch cases and if cases with where clauses as well.

Generics

Swift provides generics that make it possible to write code that is not specific to a type and can be utilized for different types.

Optional chaining

Swift provides optional types that can have some or none values. Swift also provides optional chaining to use optionals safely and efficiently. Optional chaining empowers us to query and call properties, methods, and subscripts on optional types that may be nil.

Extensions

Swift provides extensions that are similar to categories in Objective-C. Extensions add new functionality to an existing class, structure, enumeration, or protocol type, even if it is closed-source.

Objective-C and Swift bridging headers

Bridging headers empower us to mix Swift with Objective-C in our projects. This functionality makes it possible to use our previously written Objective-C code in Swift projects and vice versa.

Automatic Reference Counting

Swift handles memory management through Automatic Reference Counting (ARC), like Objective-C and unlike languages such as Java and C#, which utilize garbage collection. ARC is used to initialize and de-initialize the resources, thereby releasing memory allocations of the class instances when they are no longer required. ARC tracks, retains, and releases in the code instances to manage the memory resources effectively.

REPL and Playground

Xcode provides the Read Eval Print Loop (REPL) command-line environment to experiment with the Swift programming language without the need to write a program. Also, Swift provides Playgrounds, which enable us to test Swift code snippets quickly and see the results in real time via a visual interface. Source codes for the first ten chapters of this book are provided as Playgrounds in the GitHub repo and Packt Publishing website.

Language basics

This section will provide a brief introduction to the basics of the Swift programming language. Topics in the upcoming subsections of this chapter will be explained in detail in later chapters.

Types

Types are designated units of composition in Swift. Classes, structs, enums, functions, closures, and protocols can become types.

Swift is a type-safe language. This means that we cannot change the type of a constant, variable, or expression once we define it. Also, the type-safe nature of Swift empowers us to find type mismatches during compile time.

Type inference

Swift provides type inference. Swift infers the type of a variable, constant, or expression automatically, so we do not need to specify the types while defining them. Let's look at the following example:

let pi = 3.14159 
var primeNumber = 691 
let name = "my name" 

In this example, Swift infers pi as Double, primeNumber as Int, and name as String. If we need special types such as Int64, we will need to annotate the type.

Type annotation

In Swift, it is possible to annotate types, or in other words, explicitly specify the type of a variable or expression. Let's look at the following example:

let pi: Double = 3.14159 
let piAndPhi: (Double, Double) = (3.14159, 1.618) 
func ourFunction(a: Int) { /* ... */ } 

In this example, we define a constant (pi) annotated as Double, a tuple named piAndPhi annotated as (Double, Double), and a parameter of ourFunction as Int.

Type aliases

Type aliases define an alternative name for an existing type. We define type aliases with the typealias keyword. Type aliases are useful when we want to refer to an existing type by a name that is contextually more appropriate, such as when working with data of a specific size from an external source. For instance, in the following example, we provide an alias for an unsigned 32-bit integer that can be used later in our code:

typealias UnsignedInteger = UInt32 

The typealias definitions can be used to simplify the closure and function definitions as well.

Type casting

Type casting is a way to check the type of an instance and/or deal with that instance as if it is a different superclass or subclass from somewhere else in its class hierarchy. There are two types of operator to check and cast types as the following:

  • Type check operator (is): This checks whether an instance is of a definite subclass type.
  • Type cast operator (as and as?): A constant or variable of a definite class type may refer to an instance of a subclass under the hood. If this is the case, we can try to downcast it to the subclass type with as.

Type safety, type inference, annotation, aliases and type casting will be covered in detail in Chapter 3, Types and Type Casting.

Immutability

Swift makes it possible to define variables as mutable and immutable. The let keyword is used for immutable declarations and the var keyword is used for mutable declarations. Any variable that is declared with the let keyword will not be open to change. In the following examples, we define aMutableString with the var keyword so that we will be able to alter it later on; in contrast, we will not be able to alter aConstString that is defined with the let keyword:

var aMutableString = "This is a variable String" 
let aConstString = "This is a constant String" 

In FP, it is recommended to define properties as constants or immutables with let as much as possible. Immutable variables are easier to track and less error-prone. In some cases, such as CoreData programming, the software development kit (SDK) requires mutable properties; however, in these cases, it is recommended to use mutable variables.

Immutability and stateless programming will be covered in detail in Chapter 9, Importance of Immutability.

Tuples

Swift provides tuples so that they can be used to group multiple values/types into a single compound value. Consider the following example:

let http400Error = (400, "Bad Request") 
// http400Error is of type (Int, String), and equals (400, "Bad Request") 

// Decompose a Tuple's content 
let (requestStatusCode, requestStatusMessage) = http400Error 

Tuples can be used as return types in functions to implement multi-return functions as well.

Optionals

Swift provides optionals so they can be used in situations where a value may be absent. An optional will have some or none values. The ? symbol is used to define a variable as optional. Consider the following example:

// Optional value either contains a value or contains nil 
var optionalString: String? = "A String literal" 
optionalString = nil 

The ! symbol can be used to forcefully unwrap the value from an optional. For instance, the following example forcefully unwraps the optionalString variable:

optionalString = "An optional String" 
print(optionalString!) 

Force unwrapping the optionals may cause errors if the optional does not have a value, so it is not recommended to use this approach as it is very hard to be sure if we are going to have values in optionals in different circumstances. The better approach would be to use the optional binding technique to find out whether an optional contains a value. Consider the following example:

let nilName: String? = nil 
if let familyName = nilName { 
    let greetingfamilyName = "Hello, Mr. \(familyName)" 
} else { 
    // Optional does not have a value 
} 

Optional chaining is a process to query and call properties, methods, and subscripts on an optional that might currently be nil. Optional chaining in Swift is similar to messaging nil in Objective-C, but in a way that works for any type and can be checked for success or failure. Consider the following example:

class Residence { 
    var numberOfRooms = 1 
} 

class Person { 
    var residence: Residence? 
} 

let jeanMarc = Person() 
// This can be used for calling methods and subscripts through optional chaining too 
if let roomCount = jeanMarc.residence?.numberOfRooms { 
    // Use the roomCount 
} 

In this example, we were able to access numberOfRooms, which was a property of an optional type (Residence) using optional chaining.

Optionals and optional binding and chaining will be covered in detail in Chapter 7, Dealing with Optionals.

Basic operators

Swift provides the following basic operations:

  • The = operator for assignments, similar to many different programming languages.
  • The + operator for addition, - for subtraction, * for multiplication, / for division, and % for remainders. These operators are functions that can be passed to other functions.
  • The -i operator for unary minus and +i for unary plus operations.
  • The +=, -=, and *= operators for compound assignments.
  • The a == b operator for equality, a != b for inequality, and a>b, a<b, and a<=b for greatness comparison.
  • The ternary conditional operator, question ? answer1: answer2.
  • nil coalescing a ?? b unwraps optional a if it has a value and returns a default value b if a is nil.
  • Range operators:
    • Closed range (a...b) includes the values a and b
    • Half-open range (a..<b) includes a but does not include b
  • Logical operators:
    • The !a operator is NOT a
    • The a && b operator is logical AND
    • The a || b operator is logical OR

Strings and characters

In Swift, String is an ordered collection of characters. String is a structure and not a class. Structures are value types in Swift; therefore, any String is a value type and passed by values, not by references.

Immutability

Strings can be defined with let for immutability. Strings defined with var will be mutable.

String literals

String literals can be used to create an instance of String. In the following code example, we define and initialize aVegetable with the String literal:

let aVegetable = "Arugula" 

Empty Strings

Empty Strings can be initialized as follows:

// Initializing an Empty String 
var anEmptyString = "" 
var anotherEmptyString = String() 

These two strings are both empty and equivalent to each other. To find out whether a String is empty, the isEmpty property can be used as follows:

if anEmptyString.isEmpty { 
    print("String is empty") 
} 

Concatenating strings and characters

Strings and characters can be concatenated as follows:

let string1 = "Hello" 
let string2 = " Mr" 
var welcome = string1+string2 

var instruction = "Follow us please" 
instruction += string2 

let exclamationMark: Character = "!" 
welcome.append(exclamationMark) 

String interpolation

String interpolation is a way to construct a new String value from a mix of constants, variables, literals, and expressions by including their values inside a String literal. Consider the following example:

let multiplier = 3 
let message = "\(multiplier) times 7.5 is \(Double (multiplier) * 7.5)" 
// message is "3 times 2.5 is 22.5" 

String comparison

Strings can be compared with == for equality and != for inequality.

The hasPrefix and hasSuffix methods can be used for prefix and suffix equality checking.

Collections

Swift provides typed collections such as array, dictionaries, and sets. In Swift, unlike Objective-C, all elements in a collection will have the same type, and we will not be able to change the type of a collection after defining it.

We can define collections as immutable with let and mutable with var, as shown in the following example:

// Arrays and Dictionaries 
var cheeses = ["Brie", "Tete de Moine", "Cambozola", "Camembert"] 
cheeses[2] = "Roquefort" 
var cheeseWinePairs = [ 
    "Brie":"Chardonnay", 
    "Camembert":"Champagne", 
    "Gruyere":"Sauvignon Blanc" 
] 

cheeseWinePairs ["Cheddar"] = "Cabarnet Sauvignon" 
// To create an empty array or dictionary 
let emptyArray = [String]() 
let emptyDictionary = Dictionary<String, Float>() 
cheeses = [] 
cheeseWinePairs = [:] 

The for-in loops can be used to iterate over the items in collections.

Control flows

Swift provides different control flows that are explained in the following subsections.

for loops

Swift provides for and for-in loops. We can use the for-in loop to iterate over items in a collection, a sequence of numbers such as ranges, or characters in a string expression. The following example presents a for-in loop to iterate through all items in an Int array:

let scores = [65, 75, 92, 87, 68] 
var teamScore = 0 

for score in scores { 
    if score > 70 { 
        teamScore = teamScore + 3 
    } else { 
        teamScore = teamScore + 1 
    } 
} 

and over dictionaries:

for (cheese, wine) in cheeseWinePairs{ 
    print("\(cheese): \(wine)") 
} 

As C styles for loops with incrementers/decrementers are removed from Swift 3.0, it is recommended to use for-in loops with ranges instead, as follows:

var count = 0 
for i in 0...3 { 
    count + = i 
} 

while loops

Swift provides while and repeat-while loops. A while or repeat-while loop performs a set of expressions until a condition becomes false. Consider the following example:

var n = 2 
while n < 100 { 
    n = n * 2 
} 
var m = 2 
repeat { 
    m = m * 2 
} while m < 100 

The while loop evaluates its condition at the beginning of each iteration. The repeat-while loop evaluates its condition at the end of each iteration.

The stride functions

stride functions enable us to iterate through ranges with a step other than one. There are two stride functions: the stride to function, which iterates over exclusive ranges, and stride through, which iterates over inclusive ranges. Consider the following example:

let fourToTwo = Array(stride(from: 4, to: 1, by: -1)) // [4, 3, 2] 
let fourToOne = Array(stride(from:4, through: 1, by: -1)) // [4, 3, 2, 1] 

if

Swift provides if to define conditional statements. It executes a set of statements only if the condition statement is true. For instance, in the following example, the print statement will be executed because anEmptyString is empty:

var anEmptyString = "" 
if anEmptyString.isEmpty { 
    print("An empty String") 
} else { 
    // String is not empty. 
} 

Switch

Swift provides the switch statement to compare a value against different matching patterns. The related statement will be executed once the pattern is matched. Unlike most other C-based programming languages, Swift does not need a break statement for each case and supports any value types. Switch statements can be used for range matching, and where clauses in switch statements can be used to check for additional conditions. The following example presents a simple switch statement with additional conditional checking:

let aNumber = "Four or Five" 
switch aNumber { 
    case "One": 
        let one = "One" 
    case "Two", "Three": 
        let twoOrThree = "Two or Three" 
    case let x where x.hasSuffix("Five"): 
        let fourOrFive = "it is \(x)" 
    default: 
    let anyOtherNumber = "Any other number" 
} 

Guard

A guard statement can be used for early exits. We can use a guard statement to require that a condition must be true in order for the code after the guard statement to be executed. The following example presents the guard statement usage:

func greet(person: [String: String]) { 
    guard let name = person["name"] else { 
        return 
    } 
    print("Hello Ms\(name)!") 
} 

In this example, the greet function requires a value for a person's name; therefore, it checks whether it is present with the guard statement, otherwise it will return and not continue to execute. As can be seen from the example, the scope of the guarded variable is not only the guard code block, so we were able to use name after the guard code block in our print statement.

Functions

Functions are self-contained blocks of code that perform a specific task.

In Swift, functions are first-class citizens, meaning that they can be stored, passed, and returned. Functions can be curried and defined as higher-order functions that take other functions as their arguments.

Functions in Swift can have multiple input parameters and multiple returns using tuples. Let's look at the following example:

func greet(name: String, day: String) ->String { 
    return "Hello \(name), today is \(day)" 
} 

greet(name: "Francois", day:"Saturday") 

Functions can have variadic parameters. Consider the following example:

// Variable number of arguments in functions - Variadic Parameters 
func sumOf(numbers: Int...) -> (Int, Int) { 
    var sum = 0 
    var counter = 0 
    for number in numbers { 
        sum += number 
        counter += 1 
    } 
    return (sum, counter) 
} 

sumOf() 
sumOf(numbers: 7, 9, 45) 

Functions can have in-out parameters. Consider the following example:

func swapTwoInts ( a: inout Int, b: inout Int) { 
    let temporaryA = a 
    a = b 
    b = temporaryA 
} 

The in-out parameters are not favorable in functional Swift as they mutate states and make functions impure.

In Swift, we can define nested functions. The following example presents a function named add nested inside another function. Nested functions can access the data in scope of their parent function. In this example, the add function has access to the y variable:

func returnTwenty() ->Int { 
    var y = 10 
    func add() { 
        y += 10 
    } 
    add() 
    return y 
} 

returnTwenty() 

In Swift, functions can return other functions. In the following example, the makeIncrementer function returns a function that receives an Int value and returns an Int value (Int ->Int):

func makeIncrementer() -> ((Int) ->Int) { 
    func addOne(number: Int) ->Int { 
        return 1 + number 
    } 
    return addOne 
} 

var increment = makeIncrementer() 
increment(7) 

Closures

Closures are self-contained blocks of code that provide a specific functionality and can be stored, passed around, and used in the code. Closures are the equivalent of blocks in C and Objective-C. Closures can capture and store references to any constants and variables from the context in which they are defined. Nested functions are special cases of closures.

Closures are reference types that can be stored as variables, constants, and type aliases. They can be passed to and returned from functions.

The following examples present different declarations of closures in Swift from the website, http://goshdarnclosuresyntax.com:

// As a variable: 
var closureName: (parameterTypes) -> (returnType) 

//As a type alias: 
typealias closureType = (parameterTypes) -> (returnType) 

//As an argument to a function call: 
func Name({ (ParameterTypes) -> (ReturnType) in statements }) 

Closures and first-class, higher-order, and pure functions will be covered in detail in Chapter 2, Functions and Closures.

The map, filter, and reduce functions

Swift provides map, filter, and reduce functions, which are higher-order functions.

The map function

The map function is a higher-order function that solves the problem of transforming the elements of an array using a function. Consider the following example:

let numbers = [10, 30, 91, 50, 100, 39, 74] 
var formattedNumbers: [String] = [] 

for number in numbers { 
    let formattedNumber = "\(number)$" 
    formattedNumbers.append(formattedNumber) 
} 

let mappedNumbers = numbers.map{ "\($0)$" } 

The filter function

The filter function is a higher-order function that takes a function that, given an element in the array, returns Bool, indicating whether the element should be included in the resulting array. Consider the following example:

let evenNumbers = numbers.filter { $0 % 2 == 0 } 

The reduce function

The reduce function is a higher-order function that reduces an array to a single value. It takes two parameters: a starting value and a function, which takes a running total and an element of the arrays as parameters and returns a new running total. Consider the following example:

let total = numbers.reduce(0) { $0 + $1 } 

The map, filter, and reduce functions accept a closure as the last parameter, so we were able to use the trailing closure syntax. These higher-order functions will be covered in detail in Chapter 6, Map, Filter, and Reduce.

Enumerations

In Swift, an enumeration defines a common type for related values and enables us to work with those values in a type-safe way. Values provided for each enumeration member can be a String, Character, Int, or any floating-point type. Enumerations can store associated values of any given type, and the value types can be different for each member of the enumeration, if needed. Enumeration members can come pre-populated with default values (called raw values), which are all of the same type. Consider the following example:

enum MLSTeam { 
    case montreal 
    case toronto 
    case newYork 
    case columbus 
    case losAngeles 
    case seattle 
} 

let theTeam = MLSTeam.montreal 

Enumeration values can be matched with a switch statement, which can be seen in the following example:

switch theTeam { 
case .montreal: 
    print("Montreal Impact") 
case .toronto: 
    print("Toronto FC") 
case .newYork: 
    print("NewyorkRedbulls") 
case .columbus: 
    print("Columbus Crew") 
case .losAngeles: 
    print("LA Galaxy") 
case .seattle: 
    print("Seattle Sounders") 
} 

Enumerations in Swift are actually algebraic data types that are types created by combining other types. Consider the following example:

enum NHLTeam { case canadiens, senators, rangers, penguins, blackHawks, capitals } 

enum Team { 
    case hockey(NHLTeam) 
    case soccer(MLSTeam) 
} 

struct HockeyAndSoccerTeams { 
    var hockey: NHLTeam 
    var soccer: MLSTeam 
} 

The MLSTeam and NHLTeam enumerations each have six potential values. If we combine them, we will have two new types. A Team enumeration can be either NHLTeam or MLSTeam, so it has 12 potential values that are the sum of NHLTeam and MLSTeam potential values. Therefore, Team, an enumeration, is a sum type.

To have a HockeyAndSoccerTeams structure, we need to choose one value for NHLTeam and one for MLSTeam so that it has 36 potential values that are the product of NHLTeam and MLSTeam values. Therefore, HockeyAndSoccerTeams is a product type.

In Swift, an enumeration's option can have multiple values. If it happens to be the only option, then this enumeration becomes a product type. The following example presents an enumeration as a product type:

enum HockeyAndSoccerTeams { 
    case value(hockey: NHLTeam, soccer: MLSTeam) 
} 

As we can create sum or product types in Swift, we can say that Swift has first-class support for algebraic data types.

Enumerations and pattern matching will be covered in detail in Chapter 4, Enumerations and Pattern Matching.

Generics

Generic code enables us to write flexible and reusable functions and types that can work with any type, subject to requirements that we define. For instance, the following function that uses in-out parameters to swap two values can only be used with Int values:

func swapTwoIntegers(a: inout Int, b: inout Int) { 
    let tempA = a 
    a = b 
    b = tempA 
} 

To make this function work with any type, generics can be used, as shown in the following example:

func swapTwoValues<T>(a: inout T, b: inout T) { 
    let tempA = a 
    a = b 
    b = tempA 
} 

Generics will be covered in detail in Chapter 5, Generics and Associated Type Protocols.

Classes and structures

Classes and structures are general-purpose, flexible constructs that become the building blocks of a program's code. They have the following features:

  • Properties can be defined to store values
  • Methods can be defined to provide functionality
  • Subscripts can be defined to provide access to their values using subscript syntax
  • Initializers can be defined to set up their functionality beyond a default implementation
  • They can conform to protocols to provide standard functionality of certain kinds

Classes versus structures

This section compares classes and structures:

  • Inheritance enables one class to inherit the characteristics of another
  • Type casting enables us to check and interpret the type of a class instance at runtime
  • De-initializers enable an instance of a class to free any resources it has assigned
  • Reference Counting allows more than one reference to a class instance
  • Structures are value types so they are always copied when they are passed around in code
  • Structures do not use Reference Counting
  • Classes are reference types

Choosing between classes and structures

Consider creating a structure when one or more of the following conditions apply:

  • The structure's primary purpose is to encapsulate a few relatively simple data values
  • It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of the structure
  • Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced
  • The structure does not need to inherit properties or behavior from another existing type

Examples of good candidates for structures include the following:

  • The size of a geometric shape
  • A point in a 3D coordinate system

Identity operators

As classes are reference types, it is possible for multiple constants and variables to refer to the same single instance of class behind the scenes. To find out if two constants or variables refer to the same instance of a class exactly, Swift provides the following identity operators:

  • Identical to (===)
  • Not identical to (!==)

Properties

Properties associate values with a particular class, structure, or enumeration. Swift enables us to set sub-properties of a structure property directly without needing to set the entire object property to a new value. All structures have an automatically generated member-wise initializer, which can be used to initialize the member properties of new structure instances. This is not true for class instances.

Property observers

Property observers are used to respond to change in a property's value. Property observers are called every time a property's value is set, even if the new value is the same as the property's current value. We have the option to define either or both of the following observers on a property:

  • The willSet observer is called just before the value is stored
  • The didSet observer is called immediately after the new value is stored

The willSet and didSet observers are not called when a property is set in an initializer before delegation takes place.

Methods

Methods are functions that are associated with a particular type. Instance methods are functions that are called on an instance of a particular type. Type methods are functions that are called on the type itself.

The following example presents a class containing a type method that is named someTypeMethod():

class AClass { 
    class func someTypeMethod() { 
        // type method body 
    } 
} 
// We can call this method as follows: 
AClass.someTypeMethod() 

Subscripts

Subscripts are shortcuts to access the member elements of a collection, list, sequence, or any custom type that implement subscripts. Consider the following example:

struct TimesTable { 
    let multiplier: Int 
    subscript(index: Int) ->Int { 
        return multiplier * index 
    } 
} 

let fiveTimesTable = TimesTable(multiplier: 5) 
print("six times five is \(fiveTimesTable[6])") 
// prints "six times five is 30" 

Inheritance

A class can inherit methods, properties, and other characteristics from another class:

class SomeSubClass: SomeSuperClass 

Swift classes do not inherit from a universal base class. Classes that we define without specifying a superclass automatically become base classes for us to build on. To override a characteristic that would otherwise be inherited, we prefix our overriding definition with the override keyword. An overridden method, property, or subscript can call the superclass version by calling super. To prevent overrides, the final keyword can be used.

Initialization

The process of preparing an instance of a class, structure, or enumeration for use is called initialization. Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an intermediate state. We can modify the value of a constant property at any point during initialization as long as it is set to a definite value by the time initialization finishes. Swift provides a default initializer for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself. Consider the following example:

class ShoppingItem { 
    var name: String? 
    var quantity = 1 
    var purchased = false 
  } 
var item = ShoppingItem() 

The struct types automatically receive a member-wise initializer if we do not define any of our own custom initializers, even if the struct's stored properties do not have default values.

Swift defines two kinds of initializers for class types:

  • Designated initializers: Methods that are able to fully initialize the object
  • Convenience initializers: Methods that rely on other methods to complete initialization

De-initialization

A de-initializer is called immediately before a class instance is deallocated. Swift automatically deallocates instances when they are no longer needed in order to free up resources.

Automatic Reference Counting

Reference Counting only applies to instances of classes. Structures and enumerations are value types, not reference types, and are not stored and passed by reference.

Weak references can be used to resolve strong reference cycles and can be defined as follows:

weak var aWeakProperty 

An unowned reference does not keep a strong reference hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is always defined as a non-optional type. A closure capture list can be used to resolve closure strong-reference cycles.

A capture in a closure can be defined as an unowned reference when the closure and the instance that it captures will always refer to each other and be deallocated at the same time.

A capture as a weak reference can be defined when the capture's reference may become nil at some point in the future. Weak references are always of an optional type. Consider the following example:

class AClassWithLazyClosure { 
    lazy var aClosure: (Int, String) -> String = { 
      [unowned self] (index: Int, stringToProcess: String) -> String in 
      // closure body goes here 
        return "" 
    } 
} 

Classes, objects, and reference types will be covered in detail in Chapter 10, The Best of Both Worlds - Combining FP Paradigms with OOP.

Any and AnyObject

Swift provides two special type aliases to work with non-specific types:

  • AnyObject can represent an instance of any class type
  • Any can represent an instance of any type, including structs, enumerations, and function types

The Any and AnyObject type aliases must be used only when we explicitly require the behavior and capabilities that they provide. Being precise about the types we expect to work with in our code is a better approach than using the Any and AnyObject types as they can represent any type and pose dynamism instead of safety. Consider the following example:

class Movie { 
    var director: String 
    var name: String 
    init(name: String, director: String) { 
        self.director = director 
        self.name = name 
    } 
} 

let objects: [AnyObject] = [ 
    Movie(name: "The Shawshank Redemption", director: "Frank Darabont"), 
    Movie(name: "The Godfather", director: "Francis Ford Coppola") 
] 

for object in objects { 
    let movie = object as! Movie 
    print("Movie: '\(movie.name)', dir. \(movie.director)") 
} 

// Shorter syntax 
for movie in objects as! [Movie] { 
    print("Movie: '\(movie.name)', dir. \(movie.director)") 
} 

Nested types

Enumerations are often created to support a specific class or structure's functionality. Likewise, it can be convenient to declare utility classes and structures purely to use within the context of a complex type.

Swift enables us to declare nested types, whereby we nest supporting enumerations, classes, and structures within the definition of the type that they support. The following example, borrowed from The Swift Programming Language by Apple Inc., presents nested types:

struct BlackjackCard { 
    // nested Suit enumeration 
    enum Suit: Character { 
        case spades = "♠", 
        hearts = "♡", 
        diamonds = "♢", 
        clubs = "♣" 
    } 

    // nested Rank enumeration 
    enum Rank: Int { 
        case two = 2, three, four, five, six, seven, eight, nine, ten 
        case jack, queen, king, ace 

        // nested struct 
        struct Values { 
            let first: Int, second: Int? 
        } 

        var values: Values { 
            switch self { 
            case .ace: 
                return Values(first: 1, second: 11) 
            case .jack, .queen, .king: 
                return Values(first: 10, second: nil) 
            default: 
                return Values(first: self.rawValue, second: nil) 
            } 
        } 
    } 

    let rank: Rank, suit: Suit 

    var description: String { 
        var output = "suit is \(suit.rawValue)," 
        output += "value is \(rank.values.first)" 
        if let second = rank.values.second { 
            output += " or \(second)" 
        } 
        return output 
    } 
} 

Protocols

A protocol defines signatures or types of methods, properties, and other requirements that fit to a specific task or piece of functionality. The protocol doesn't actually implement any functionality. It only describes what an implementation will look like. A class, structure, or enumeration that provides an actual implementation of requirements can adopt the protocol. Protocols use the same syntax as normal methods but are not allowed to specify default values for method parameters.

The is operator can be used to check whether an instance conforms to a protocol. We can check for protocol conformance only if our protocol is marked with @objc for classes. The as operator can be used to cast to a specific protocol.

Protocols as types

Any protocol that we define will become a fully-fledged type to use in our code. We can use a protocol as follows:

  • A parameter type or return type in a function, method, or initializer
  • The type of a constant, variable, or property
  • The type of items in an array, dictionary, or another container

Let's look at the following example:

protocol ExampleProtocol { 
    var simpleDescription: String { get } 
    mutating func adjust() 
} 

// Classes, enumerations and structs can all adopt protocols. 
class SimpleClass: ExampleProtocol { 
    var simpleDescription: String = "A very simple class example" 
    var anotherProperty: Int = 79799 

    func adjust() { 
        simpleDescription += "Now 100% adjusted..." 
    } 
} 

var aSimpleClass = SimpleClass() 
aSimpleClass.adjust() 
let aDescription = aSimpleClass.simpleDescription 

struct SimpleStructure: ExampleProtocol { 
    var simpleDescription: String = "A simple struct" 
    // Mutating to mark a method that modifies the structure - For      
    classes we do not need to use mutating keyword 
    mutating func adjust() { 
        simpleDescription += "(adjusted)" 
    } 
} 

var aSimpleStruct = SimpleStructure() 
aSimpleStruct.adjust() 
let aSimpleStructDescription = aSimpleStruct.simpleDescription 

Extensions

Extensions add new functionality to an existing class, structure, enumeration, or protocol. This includes the ability to extend types for which we do not have access to the original source code.

Extensions in Swift enables us to perform the following:

  • Define instance methods and type methods
  • Provide new initializers
  • Define and use new nested types
  • Define subscripts
  • Add computed properties and computed static properties
  • Make an existing type conform to a new protocol

Extensions enable us to add new functionality to a type, but we will not be able to override the existing functionality.

In the following example, we extend AType by making it conform to two protocols:

extension AType: AProtocol, BProtocol { } 

The following example presents an extension to Double by adding computed properties:

extension Double { 
    var mm: Double{ returnself / 1_000.0 } 
    var ft: Double{ returnself / 3.2884 } 
} 

let threeInch = 76.2.mm 
let fiveFeet = 5.ft 

Protocol extensions

Protocol extensions allow us to define behavior on protocols rather than in each type's individual conformance or global function. By creating an extension on a protocol, all conforming types automatically gain this method implementation without any additional modification. We can specify constraints that conforming types must satisfy before the methods and properties of the extensions are available when we define a protocol extension. For instance, we can extend our ExampleProtocol to provide default functionality as follows:

extension ExampleProtocol { 
    var simpleDescription: String { 
        get { 
            return "The description is: \(self)" 
        } 
        set { 
            self.simpleDescription = newValue 
        } 
    } 

    mutating func adjust() {
        self.simpleDescription = "adjusted simple description" 
    } 
} 

Access control

Access control restricts access to parts of our code from code in other source files and modules. Access levels are as follows:

  • Open and Public accesses enable entities to be used within any source file from their defining module and also in a source file from another module that imports the defining module. Open access enables subclassing, as opposed to Public access, which disallows subclassing.
  • Internal access enables entities to be used within any source file from their defining module, but not in any source file outside of this module.
  • File-private access restricts the use of an entity to its defining source file.
  • Private access restricts the use of an entity to its enclosing declaration.

Swift evolution proposals SE-0025 and SE-0117 explain the motivation, proposed solution, and provide code examples for access levels.

Error handling

Swift provides support to throw, catch, propagate, and manipulate recoverable errors at runtime.

Value types should conform to the Error protocol to be represented as errors. The following example presents some 4xx and 5xx HTTP errors as enum:

enum HttpError: Error { 
    case badRequest 
    case unauthorized 
    case forbidden 
    case requestTimeOut 
    case unsupportedMediaType 
    case internalServerError 
    case notImplemented 
    case badGateway 
    case serviceUnavailable 
} 

We will be able to throw errors using the throw keyword and mark functions that can throw errors with the throws keyword.

We can use a do-catch statement to handle errors by running a block of code. The following example presents JSON parsing error handling in a do-catch statement:

protocol HttpProtocol{ 
    func didRecieveResults(results: Any) 
} 

struct WebServiceManager { 
    var delegate:HttpProtocol? 
    let data: Data 
    func test() { 
        do { 
            let jsonResult = try JSONSerialization.jsonObject(with:     
            self.data, options: JSONSerialization.ReadingOptions
            .mutableContainers) 
            self.delegate?.didRecieveResults(results: jsonResult) 
        } catch let error { 
            print("json error" + error.localizedDescription) 
        } 
    } 
} 

We can use a defer statement to execute a set of statements just before code execution leaves the current code block, regardless of how the execution leaves the current block of code.

Summary


This chapter began by explaining why FP matters, and then it introduced the key paradigms of FP in general. Furthermore, it introduced the basics of the Swift programming language with code examples. At this point, we should have a broad view of FP concepts and the Swift programming language. All the topics in this chapter will be covered in detail in the upcoming chapters.

We will begin to dive deeper into these topics with functions, as they are the most essential building blocks in FP. Therefore, the following chapter will explain functions and give examples for pure, first-class, higher-order, and nested functions. Also, it will explain slightly more advanced topics such as memoization, function currying, and composition.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Written for the latest version of Swift, this is a comprehensive guide that introduces iOS, Web and macOS developers to the all-new world of functional programming that has so far been alien to them
  • Get familiar with using functional programming alongside existing OOP techniques so you can get the best of both worlds and develop clean, robust, and scalable code
  • Develop a case study on example backend API with Swift and Vapor Framework and an iOS application with Functional Programming, Protocol-Oriented Programming, Functional Reactive Programming, and Object-Oriented Programming techniques

Description

Swift is a multi-paradigm programming language enabling you to tackle different problems in various ways. Understanding each paradigm and knowing when and how to utilize and combine them can lead to a better code base. Functional programming (FP) is an important paradigm that empowers us with declarative development and makes applications more suitable for testing, as well as performant and elegant. This book aims to simplify the FP paradigms, making them easily understandable and usable, by showing you how to solve many of your day-to-day development problems using Swift FP. It starts with the basics of FP, and you will go through all the core concepts of Swift and the building blocks of FP. You will also go through important aspects, such as function composition and currying, custom operator definition, monads, functors, applicative functors,memoization, lenses, algebraic data types, type erasure, functional data structures, functional reactive programming (FRP), and protocol-oriented programming(POP). You will then learn to combine those techniques to develop a fully functional iOS application from scratch

What you will learn

[*]Understand what functional programming is and why it matters [*]Understand custom operators, function composition, currying, recursion, and memoization [*] Explore algebraic data types, pattern matching, generics, associated type protocols, and type erasure [*] Get acquainted with higher-kinded types and higher-order functions using practical examples [*]Get familiar with functional and non-functional ways to deal with optionals [*]Make use of functional data structures such as semigroup, monoid, binary search tree, linked list, stack, and lazy list [*]Understand the importance of immutability, copy constructors, and lenses [*] Develop a backend API with Vapor [*]Create an iOS app by combining FP, OOP, FRP, and POP paradigms

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Apr 26, 2017
Length 316 pages
Edition : 2nd Edition
Language : English
ISBN-13 : 9781787284500
Vendor :
Apple
Category :

Table of Contents

19 Chapters
Title Page Chevron down icon Chevron up icon
Credits Chevron down icon Chevron up icon
About the Author Chevron down icon Chevron up icon
About the Reviewer Chevron down icon Chevron up icon
www.PacktPub.com Chevron down icon Chevron up icon
Customer Feedback Chevron down icon Chevron up icon
Dedication Chevron down icon Chevron up icon
Preface Chevron down icon Chevron up icon
Getting Started with Functional Programming in Swift Chevron down icon Chevron up icon
Functions and Closures Chevron down icon Chevron up icon
Types and Type Casting Chevron down icon Chevron up icon
Enumerations and Pattern Matching Chevron down icon Chevron up icon
Generics and Associated Type Protocols Chevron down icon Chevron up icon
Map, Filter, and Reduce Chevron down icon Chevron up icon
Dealing with Optionals Chevron down icon Chevron up icon
Functional Data Structures Chevron down icon Chevron up icon
Importance of Immutability Chevron down icon Chevron up icon
Best of Both Worlds and Combining FP Paradigms with OOP Chevron down icon Chevron up icon
Case Study - Developing an iOS Application with FP and OOP Paradigms Chevron down icon Chevron up icon

Customer reviews

Filter icon Filter
Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%

Filter reviews by


No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.