Loading…
A Kotlin Style .copy Function for Swift Structs
2023-10-18
- Source
- Shopify
- Published
- Added to Yomu
Summary
Immutable state objects are used to keep rendering code from modifying shared values, supporting clearer value origins, fewer bugs, and more focused testing. Kotlin data classes provide a copy function that replaces selected fields while preserving the rest, allowing the new object to become the source of truth. Swift structs lack an equivalent convenience, and defining a complete initializer plus a parameter-based copy method becomes cumbersome, particularly with many or nested properties. Optional properties expose a further issue: nil must sometimes mean “set this field to nil,” not “use the existing value.” A functional builder closure solves that distinction by collecting overrides while retaining the original struct’s values for other fields, and a Sourcery stencil can generate the initializer and builder boilerplate.
Context
The work addresses the difficulty of applying Kotlin’s immutable-object and copy-function pattern to Swift structs. Swift lacks a similar copy function, and optional properties make a copy method based on nil defaults unable to distinguish clearing a value from leaving the current value unchanged.
Approach / What changed
The proposed implementation defines an initializer covering every struct field, then uses a functional builder closure to capture overrides for selected properties while taking the original struct’s values for the remaining fields. A Sourcery stencil template generates the initializer and builder boilerplate.
Takeaways
- A copy method whose override parameters default to nil cannot set an optional property to nil when nil also means “retain the current value.”
- The functional builder pattern lets callers specify only selected property overrides while preserving all other values from the original struct.
- Sourcery is used with a stencil template to generate the copy initializer and builder code for Swift structs.