Post

Mastering Infix Operators in Swift: Compose Functions

Learn how the order of parameters and return values affect function composition in Swift and how to improve composability using higher-order functions.

Mastering Infix Operators in Swift: Compose Functions

Let’s continue composing functions to create something bigger. Today, I want to discuss how the order of parameters and return values (function signature) impacts function composition in Swift.

Understanding Function Signatures

Consider this example:

1
let uppercased = String.uppercased(with:)

The function signature of uppercased is:

1
(String) -> (Locale?) -> String

This means uppercased takes a String as a parameter and returns another function that takes an optional Locale and returns a String.

For example:

1
let stringToBeUppercasedWithLocale = uppercased("mehmet")

The function signature of stringToBeUppercasedWithLocale is:

1
(Locale?) -> String

We can then use this function as follows:

1
let currentLocalUppercased = stringToBeUppercasedWithLocale(.current)

Why Is This Order Suboptimal?

The issue here is that we first pass the string, and then later provide the locale. However, for better function composition, we would prefer a signature where we first specify the locale and then pass the string. Ideally, the signature should be:

1
(Locale?) -> (String) -> String

This would allow us to reuse the function for multiple strings while keeping the locale fixed.

Transforming the Function Signature

To achieve this transformation, we can use a higher-order function that flips the parameter order.

Here’s a flip function to achieve this:

1
2
3
4
5
6
7
func flip<A, B, C>(_ f: @escaping (A) -> (B) -> C) -> (B) -> (A) -> C {
    { b in
        { a in
            f(a)(b)
        }
    }
}

Applying the flip Function

Using flip, we transform uppercased into a more composable version:

1
let flipUppercased = flip(uppercased)

Now, flipUppercased has the signature:

1
(Locale?) -> (String) -> String

We can now create a localized uppercase function:

1
let flipCurrentLocalUppercased = flipUppercased(.current)

Now, we can reuse flipCurrentLocalUppercased for multiple strings:

1
2
let flipStringThatIsUpperCasedMehmet = flipCurrentLocalUppercased("Mehmet")
let flipStringThatIsUpperCasedBaykar = flipCurrentLocalUppercased("Baykar")

Why This Approach Is Better

  • The function becomes more reusable by fixing the locale first.
  • It improves readability and reduces redundant code.
  • It allows better function composition in functional programming paradigms.

By flipping the parameter order, we achieve a more flexible and composable function, making Swift’s functional capabilities even more powerful.

I’ll continue sharing more insights into functional programming in Swift, so stay tuned!

☕ Support My Work

If you found this post helpful and want to support more content like this, you can buy me a coffee!

Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏

This post is licensed under CC BY 4.0 by the author.