Fundamentals 19 min read

Functional Programming in Swift: Concepts, Benefits, and Practical Examples

This article explains functional programming concepts, their importance, and how to apply them in Swift through high‑order functions, lazy evaluation, custom operators, and composable image‑filter pipelines, while also addressing common pitfalls such as nested callbacks and OCP violations.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Functional Programming in Swift: Concepts, Benefits, and Practical Examples

This article is aimed at developers who already have some Swift experience and are interested in functional programming, though anyone curious about the paradigm will find it useful.

Functional programming is defined as a programming paradigm where programs are built by applying and composing functions. It is one of many programming paradigms that classify languages based on their features, such as imperative, object‑oriented, declarative, functional, logic, mathematical, and reactive.

The author argues that functional programming is a methodology for abstracting problems, just as object‑oriented programming treats everything as objects, functional programming treats everything as functions, making functions first‑class citizens that can be passed, returned, and stored like basic types.

Why functional programming matters is illustrated by John Hughes' classic paper "Why Functional Programming Matters," which emphasizes modular design: breaking problems into sub‑problems and then gluing solutions together. The two "glue" mechanisms provided by functional languages are high‑order functions and lazy evaluation.

Glue Function – High‑Order Functions

High‑order functions allow simple functions to be combined into more complex ones, similar to building with LEGO blocks.

let newFilter: Filter = { image in
    return colorControls(h: 97, s: 8, b: 85)(colorInvert()(sobel()(image)))
}

Glue Program – Lazy Evaluation

Lazy evaluation defers computation until the result is needed, reducing unnecessary work and enabling the composition of generators and selectors.

g(f(input))

The article then presents a concrete Swift example using Core Image filters. A type alias defines a filter as a function from CIImage to CIImage :

typealias Filter = (CIImage) -> CIImage

Several basic filters are implemented (sobel edge detection, color inversion, color controls) and then combined using three strategies:

Direct nesting (hard to read and extend).

Explicit compose function:

func compose(filter1: @escaping Filter, with filter2: @escaping Filter) -> Filter {
    return { image in filter2(filter1(image)) }
}

Using compose still leads to nested calls for many filters.

3. Custom operator >>> to chain filters left‑associatively:

infix operator >>>: AdditionPrecedence
func >>>(filter1: @escaping Filter, filter2: @escaping Filter) -> Filter {
    return { image in filter2(filter1(image)) }
}

let filter = sobel() >>> colorInvert() >>> colorControls(h: 97, s: 8, b: 85)
let outputImage = filter(inputImage)

The same compositional ideas are applied to an RxSwift Observable example, showing how the Observable and Observer abstractions embody object‑oriented, protocol‑oriented, functional (Monad), and reactive paradigms simultaneously.

Next, the article tackles a real‑world UI‑networking scenario where two network requests must run sequentially. The initial implementation nests callbacks, coupling UI updates with data logic and violating the Open‑Closed Principle (OCP). The author refactors by extracting UI updates into a nested helper function, then abstracts request‑action composition using custom operators:

infix operator >>
typealias Action = () -> Void
typealias Request = (@escaping Action) -> Void

let task: Action =
    requestNaruto >> { updateStatus(text: "Syncing OnePiece", reload: (true, 0)) } >>
    requestOnePiece >> { updateStatus(text: "Success", reload: (true, 1)) }

task()

This approach eliminates deep nesting and separates concerns, though the author notes it still requires modifying the composition chain when adding new requests, thus not fully satisfying OCP.

In conclusion, the article reinforces that functional programming provides essential tools—high‑order functions and lazy evaluation—to write more modular, composable, and maintainable Swift code, and encourages developers to adopt functional thinking alongside Swift's evolving language features.

Swiftsoftware designFunctional Programminglazy-evaluationHigher-order FunctionsRxSwiftcode composition
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.