Paul Calnan's Blog
Published April 17, 2023

We often need to convert between a String value and a Data value. I have been using the following approach for years to do this conversion:

func convert(from string: String) -> Data? {
    string.data(using: .utf8)
}

func convert(from data: Data) -> String? {
    String(data: data, encoding: .utf8) 
}

Note, I'm only using functions here so the return types are explicit. Usually I would just call String.data(using:) or String.init(data:encoding:) directly. The important part is that they both return optionals.

There is a way to do this without optionals.

func convert(from string: String) -> Data {
    Data(string.utf8)
}

func convert(from data: Data) -> String {
    String(decoding: data, as: UTF8.self)
}

The optional-based approach dates all the way back to iOS 2 and Objective-C. The non-optional approach came in around iOS 8 along with Swift.

Published April 16, 2023

On the last two projects I worked on, I have used this extension on Optional:

import Foundation

extension Optional {
    func unwrap(orThrow error: @autoclosure () -> Error) throws -> Wrapped {
        guard let value = self else {
            throw error()
        }
        return value
    }

    func unwrap(or fallback: Wrapped) -> Wrapped {
        guard let value = self else {
            return fallback
        }
        return value
    }
}

The unwrap(or:) function is equivalent to, and more verbose than, the ?? operator. However, I find it works well in a chain of function calls. For example:

func fetchRecord(id: String) async throws -> Record {
    Record(fragment:
        try await client.fetch(query: RecordQuery(id: id))
            .record
            .unwrap(orThrow: ServiceError.notFound)
            .fragments
            .recordFragment
    )
}

func fetchRecords() async throws -> [Record] {
    try await client.fetch(query: RecordsQuery())
        .records
        .unwrap(or: [])
        .map {
            $0.fragments.recordFragment
        }
        .map {
            Record(fragment: $0)
        }
}

This lets me succinctly express a series of operations and transformations in a style that is similar to what you would write using Combine.

Usually, I would stop there. But I was wondering if I could merge the two functions. Something like this:

extension Optional {
    func unwrap(or fallback: @autoclosure () throws -> Wrapped) throws -> Wrapped {
        guard let value = self else {
            return try fallback()
        }
        return value
    }
}

That allows us to write this, just as before:

let value: String? = nil
print(value.unwrap(or: "nothing")

I wanted to be able also to write this, but it doesn't compile:

try print(value.unwrap(or: throw ServiceError.notFound))
error: expected expression in list of expressions
try print(value.unwrap(or: throw SomeError()))
                           ^

Why doesn't that work?

I'm trying to pass throw SomeError() as an autoclosure. This is what the Swift Programming Language book has to say about autoclosures:

An autoclosure is a closure that’s 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.

So why can't we pass throw SomeError() to as an autoclosure? It all comes down to the difference between a statement and an expression.

As a refresher:

An expression lets you access, modify, and assign values. In Swift, there are four kinds of expressions: prefix expressions, infix expressions, primary expressions, and postfix expressions. Evaluating an expression returns a value, causes a side effect, or both.

A statement groups expressions and controls the flow of execution. In Swift, there are three kinds of statements: simple statements, compiler control statements, and control flow statements.

Basically, an expression evaluates to a value and a statement does not. throw SomeError() is a statement — specifically, a control flow statement. It does not evaluate to a value, so we can't pass it as an autoclosure.

Maybe we could do this with an overload. Let's try this:

extension Optional {
    func unwrap(or error: @autoclosure () -> Error) throws -> Wrapped {
        guard let value = self else {
            throw error()
        }
        return value
    }

    func unwrap(or fallback: Wrapped) -> Wrapped {
        guard let value = self else {
            return fallback
        }
        return value
    }
}

So now we have the same function name, unwrap(or:), that we can call in either of these ways:

let value: String? = nil

do {
    print(value.unwrap(or: "nothing")
    try print(value.unwrap(or: ServiceError.notFound))
}
catch {
    print("Error: \(error)")
}

This works as expected. It prints:

nothing
Error: notFound

Things get weird, though, when we deal with optional errors:

let error: Error? = nil
print(error.unwrap(or: ServiceError.notFound)

This fails to compile with this error:

error: ambiguous use of 'unwrap(or:)'
print(error.unwrap(or: Fail()))
      ^

note: found this candidate
    func unwrap(or error: @autoclosure () -> Error) throws -> Wrapped {
         ^

note: found this candidate
    func unwrap(or fallback: Wrapped) -> Wrapped {
         ^

This isn't the end of the world — we generally don't deal with optional errors. But I don't like leaving this sort of rough edge on an API. So I think I'll stick with my original approach: Optional.unwrap(orThrow:) and Optional.unwrap(or:).

Published December 21, 2020

I have been reading a Calculus book recently and came across formulas for min and max:

\[ \begin{align} min(x, y) = \frac{x + y - |y - x|}{2} \\ max(x, y) = \frac{x + y + |y - x|}{2} \end{align} \]

Here \(\frac{x + y}{2}\) is the average of the two numbers or the midpoint between the two on the number line.

Also \(\frac{|y - x|}{2}\) is half the distance between y and x. Adding it to the midpoint gives the maximum (rightmost) value and subtracting it from the midpoint gives the minimum (leftmost) value.

This is particularly interesting coming from a programming background where:

min(x, y) := x <= y ? x : y
max(x, y) := x >= y ? x : y

I never thought of coming up with a non-procedural formula for either of these.

We can prove that \(min(x, y) = \frac{x + y - |y - x|}{2}\) and \(max(x, y) = \frac{x + y + |y - x|}{2}\) as follows:

\[ x \leq y \implies |y - x| = y - x \]

\[ x + y - |y - x| = x + y - y + x = 2x = 2 \cdot min(x,y) \]

\[ x + y + |y - x| = x + y + y - x = 2y = 2 \cdot max(x, y) \]

In both cases, swap \(x\) and \(y\) to prove the formulas for \(x \geq y\).

Published December 21, 2020

Euler's formula states that for any real number \(x\):

\[ e^{ix} = \cos x + i \sin x \]

When \(x = \pi\), Euler's formula evaluates to:

\[ e^{i\pi} + 1 = 0 \]

This is known as Euler's identity and it links five fundamental mathematical constants (\(\pi\), \(e\), \(i\), \(0\), and \(1\)) in a beautifully simple equation. Richard Feynman called the equation "the most remarkable formula in mathematics."

The formula can be interpreted as saying that the function \(e^{i\phi}\) is a unit complex number, i.e. it traces out the unit circle in the complex plane as \(\phi\) ranges through the real numbers.

We can derive Euler's formula from the Maclaurin series expansions of \(\sin x\), \(\cos x\), and \(e^x\):

\[ \begin{align} \sin x &= \sum_{n=0}^\infty \frac{(-1)^n}{(2n+1)!} x^{2n+1} \\ &= x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots \\ \cos x &= \sum_{n=0}^\infty \frac{(-1)^n}{(2n)!} x^{2n} \\ &= 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} + \cdots \\ e^x &= \sum_{n = 0}^{\infty} \frac{x^n}{n!} \\ &= 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots \end{align} \]

Thus:

\[ \begin{align} e^{ix} &= \sum_{n = 0}^{\infty} \frac{(ix)^n}{n!} \\ e^{ix} &= 1 + ix + \frac{(ix)^2}{2!} + \frac{(ix)^3}{3!} + \frac{(ix)^4}{4!} + \frac{(ix)^5}{5!} + \frac{(ix)^6}{6!} + \frac{(ix)^7}{7!} + \cdots \\ &= 1 + ix - \frac{x^2}{2!} - \frac{ix^3}{3!} + \frac{x^4}{4!} + \frac{ix^5}{5!} - \frac{x^6}{6!} - \frac{ix^7}{7!} + \cdots \\ &= \left( 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} - \cdots \right) + \left( ix - \frac{ix^3}{3!} + \frac{ix^5}{5!} - \frac{ix^7}{7!} + \cdots \right) \\ &= \left( 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} - \cdots \right) + i\left( x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \cdots \right) \\ &= \cos x + i\sin x \end{align} \]

This yields Euler's identity. Substitute \(\pi\) for \(x\). Since \(\cos \pi = -1\) and \(\sin \pi = 0\), it follows that:

\[ e^{i\pi} = -1 + 0i \]

or

\[ e^{i\pi} + 1 = 0 \]

Published May 13, 2020

Computing cryptographic hashes in Swift has gotten easier in recent times. Prior to Xcode 10, it used to be difficult to import the CommonCrypto library which did the computation. Xcode 10 added a module for that library, making it easier to do the import. But the API still looks like a C API. Using the library directly requires you to write something like this:

import CommonCrypto
import Foundation

// Compute the digest of this string:
let messageString = "The quick brown fox jumps over the lazy dog"

// Convert the string to a byte array.
let messageData = Data(messageString.utf8)

// Compute the hash using CommonCrypto.
var digestData = Data(count: Int(CC_SHA224_DIGEST_LENGTH))
digestData.withUnsafeMutableBytes { (digestBuffer: UnsafeMutableRawBufferPointer) -> Void in
    messageData.withUnsafeBytes { (messageBuffer: UnsafeRawBufferPointer) -> Void in
        _ = CC_SHA224(messageBuffer.baseAddress,
                      CC_LONG(messageBuffer.count),
                      digestBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self))
    }
}

// Convert the digestData byte buffer into a hex string.
let digestString = digestData.map { String(format: "%02hhx", $0) }.joined()

// prints 730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525
print(digestString)

That's a fair amount of boilerplate. The meat of that code — the withUnsafeMutableBytes and withUnsafeBytes calls — changed between Swift versions. I had to rewrite that code a few times to eliminate new compiler warnings and deprecations.

Rather than deal with that in production code, I wrote a small Swift library called HashAlgorithm to simplify the process.

Using it is pretty simple. Instead of the code above, you just do this:

import Foundation
import HashAlgorithm

// Compute the digest of this string:
let messageString = "The quick brown fox jumps over the lazy dog"
let digest = HashAlgorithm.SHA224.digest(messageString)

// prints 730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525
print(digest)

The digest(_:) function returns a Digest value that wraps a Data value. Its description property converts the data into a hex-string.

It supports all of the (non-deprecated) cryptographic hash algorithms currently provided by CommonCrypto: SHA1, SHA224, SHA256, SHA384, and SHA512.

The library is available on Github.

Older Posts