Supporting Literal Initialization for Custom Types in Swift

What are Swift Literals and how do they work?

Batikan Sosun
Mac O’Clock

--

Photo by Joshua Reddekopp on Unsplash

In this iOS guide, I am going to explain Swift literals, and I am going to reinforce the following topics by giving examples in order.

  • What are the Swift literals?
  • How do they work?
  • Standard literals
  • Literal initialization for custom types

What Are the Swift Literals?

Literals are digits of characters that describe constant values to be stored in properties. Literals are used to initialize or assign value to variables or constants.

How Do They Work?

In the Swift standard library, type aliases of primitive types are created. Whenever we assign any value to a variable with no type information, Swift uses those type aliases to determine what type to use for the expression.

Standard Literals

A literal is a representation of a value in source code, such as a number or a string.

Swift provides the following kinds of literals:

  • ExpressibleByArrayLiteral
  • ExpressibleByDictionaryLiteral
  • ExpressibleByIntegerLiteral
  • ExpressibleByFloatLiteral
  • ExpressibleByBooleanLiteral
  • ExpressibleByNilLiteral
  • ExpressibleByStringLiteral
  • ExpressibleByExtendedGraphemeClusterLiteral
  • ExpressibleByStringInterpolation

Let’s explain them step by step together with short examples.

1. ExpressibleByArrayLiteral

Declaration as a protocol:

associatedtype ArrayLiteralElement

The type of the elements of an array literal:

protocol ExpressibleByArrayLiteral

An array literal is a simple way of expressing a list of values. Simply surround a comma-separated list of values, instances, or literals with square brackets to create an array literal. You can use an array literal anywhere an instance of an ExpressibleByArrayLiteral type is expected: as a value assigned to a variable or constant, as a parameter to a method or initializer, or even as the subject of a nonmutating operation like map(_:) or filter(_:).

Arrays, sets, and option set all conform to ExpressibleByArrayLiteral, and your own custom types can as well. Here’s an example of creating a set and an array using array literals:

1.1 Type inference of array literals

Whenever possible, Swift’s compiler infers the full intended type of your array literal. Because Array is the default type for an array literal, without writing any other code, you can declare an array with a particular element type by providing one or more values.

In this example, the compiler infers the full type of each array literal.

2. ExpressibleByDictionaryLiteral

Declaration as a protocol.

associatedtype Key

The key type of a dictionary literal.

associatedtype Value

The value type of a dictionary literal.

protocol ExpressibleByDictionaryLiteral

A dictionary literal is a simple way of writing a list of key-value pairs. You write each key-value pair with a colon (:) separating the key and the value. The dictionary literal is made up of one or more key-value pairs, separated by commas and surrounded with square brackets.

To declare a dictionary, assign a dictionary literal to a variable or constant:

3. ExpressibleByIntegerLiteral

Declaration as a protocol.

associatedtype IntegerLiteralType

A type that represents an integer literal.

protocol ExpressibleByIntegerLiteral

The standard library integer and floating-point types, such as Int and Double, conform to the ExpressibleByIntegerLiteral protocol. You can initialize a variable or constant of any of these types by assigning an integer literal.

4. ExpressibleByFloatLiteral

Declaration as a protocol.

associatedtype FloatLiteralType

A type that represents a floating-point literal.

protocol ExpressibleByFloatLiteral

The standard library floating-point types — Float, Double, and Float80 where available—all conform to the ExpressibleByFloatLiteral protocol. You can initialize a variable or constant of any of these types by assigning a floating-point literal.

5. ExpressibleByBooleanLiteral

Declaration as a protocol.

associatedtype BooleanLiteralType

A type that represents a Boolean literal, such as Bool.

protocol ExpressibleByBooleanLiteral

Bool, DarwinBoolean, ObjCBool, and WindowsBool are treated as Boolean values. Expanding this set to include types that represent more than simple Boolean values is discouraged.

To add ExpressibleByBooleanLiteral conformance to your custom type, implement the init(booleanLiteral:) initializer that creates an instance of your type with the given Boolean value.

6. ExpressibleByNilLiteral

Declaration as a protocol.

protocol ExpressibleByNilLiteral

nil has a specific meaning in Swift—the absence of a value. Only the Optional type conforms to ExpressibleByNilLiteral. ExpressibleByNilLiteral conformance for types that use nil for other purposes is discouraged.

7. ExpressibleByStringLiteral

Declaration as a protocol.

associatedtype StringLiteralType

A type that represents a string literal.

protocol ExpressibleByStringLiteral

The String and StaticString types conform to the ExpressibleByStringLiteralprotocol. You can initialize a variable or constant of either of these types using a string literal of any length.

8. ExpressibleByExtendedGraphemeClusterLiteral

Declaration as a protocol.

associatedtype ExtendedGraphemeClusterLiteralType

A type that represents an extended grapheme cluster literal.

protocol ExpressibleByExtendedGraphemeClusterLiteral

An extended grapheme cluster is a group of one or more Unicode scalar values that approximates a single user-perceived character. Many individual characters, such as “é”, “김”, and “🇮🇳”, can be made up of multiple Unicode scalar values. These code points are combined by Unicode’s boundary algorithms into extended grapheme clusters.

The String, StaticString, and Character types conform to the ExpressibleByExtendedGraphemeClusterLiteral protocol. You can initialize a variable or constant of any of these types using a string literal that holds a single character.

9. ExpressibleByStringInterpolation

Declaration as a protocol.

associatedtype StringInterpolation

The type each segment of a string literal containing interpolations should be appended to.

protocol ExpressibleByStringInterpolation

Use string interpolation to include one or more expressions in a string literal, wrapped in a set of parentheses and prefixed by a backslash. For example:

Literal Initialization for Custom types

If you have a custom type like below struct you can initialize as literal.
For example, I will define CustomInteger struct.

And you can implement ExpressibleByIntegerLiteral protocol to Date class as an extension. It will be more useful.

Conclusion

Swift contains a group of ExpressibleByLiteral protocols that are used for custom types to be initialized with a matching literal.

Supporting initialization by literals when appropriate can significantly improve the ergonomics of custom types, making them feel like they’re built-in.

Initialization with Literals can make your Swift code more clean and direct.

Thanks for reading!

--

--

Batikan Sosun
Mac O’Clock

Tweeting tips and tricks about #swift #xcode #apple Twitter @batikansosun Weekly Swift Blogging