Functional Programming in Swift: From A to Z — The Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Functional Programming in Swift: From A to Z



Functional programming (FP) is a paradigm that treats computation as the evaluation of mathematical functions and avoids changing state and mutable data. Swift, being a multi-paradigm language, perfectly supports the functional style, especially in iOS and macOS development. In this article, we will journey from basic concepts to advanced techniques such as monads and function composition.



Fundamentals of the Functional Approach in Swift



At the core of functional programming lie several key principles:



  • Pure functions — the result depends only on the input arguments, with no side effects.
  • Data immutability — using let instead of var.
  • Functions as first-class objects — they can be passed, returned, and stored.


Let's look at a simple example of a pure function:



// Pure function: no side effectsfunc add(_ a: Int, _ b: Int) -> Int {    return a + b}

// Usagelet result = add(3, 5) // 8print(result)


Closures and Higher-Order Functions



Closures are self-contained blocks of functionality that can be passed around and used in code. They are the foundation for working with higher-order functions.



// Simple closurelet multiply = { (x: Int, y: Int) -> Int in    return x * y}

let product = multiply(4, 7) // 28print(product)


Swift provides powerful higher-order functions for working with collections:



map

map applies a transformation to each element of an array:



let numbers = [1, 2, 3, 4, 5]let squared = numbers.map { $0 * $0 }print(squared) // [1, 4, 9, 16, 25]


filter

filter selects elements that satisfy a condition:



let evenNumbers = numbers.filter { $0 % 2 == 0 }print(evenNumbers) // [2, 4]


reduce

reduce combines all elements into a single value:



let sum = numbers.reduce(0, +)print(sum) // 15


Function Composition and Currying



Composition allows combining simple functions into more complex ones. Swift does not have a built-in composition operator, but it is easy to implement:



// Composition operatorprecedencegroup CompositionPrecedence {    associativity: left    higherThan: AssignmentPrecedence}

infix operator >>>: CompositionPrecedence

func >>> <A, B, C>(left: @escaping (A) -> B, right: @escaping (B) -> C) -> (A) -> C { return { right(left($0)) }}

// Usagefunc double(_ x: Int) -> Int { x * 2 }func toString(_ x: Int) -> String { "\\(x)" }

let doubleThenString = double >>> toStringprint(doubleThenString(5)) // "10"


Currying is the transformation of a function that takes multiple arguments into a sequence of functions, each taking a single argument:



// Regular functionfunc add(_ a: Int, _ b: Int) -> Int { a + b }

// Curried versionfunc curriedAdd(_ a: Int) -> (Int) -> Int { return { b in a + b }}

let addFive = curriedAdd(5)print(addFive(3)) // 8


Monads and Functors in Swift



In functional programming, a functor is a type that can be mapped over. A monad is a functor with an additional flatMap (or >>=) operation. The most well-known examples in Swift are Optional and Array.



Optional as a Monad



let optionalValue: Int? = 5

// map — applies a function if the value is not nillet doubled = optionalValue.map { $0 * 2 }print(doubled) // Optional(10)

// flatMap

Blogs

Book Recommendations