# Compositional Initialization

**URL:** <https://forums.swift.org/t/compositional-initialization/29535>\
**Category:** Pitches\
**Created:** [October 4, 2019, 8:20pm UTC](https://forums.swift.org/t/compositional-initialization/29535 "2019-10-04T20:20:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 4, 2019, 8:20pm UTC](https://forums.swift.org/t/compositional-initialization/29535/1 "2019-10-04T20:20:37Z")

</div>

# Compositional Initalization

## Introduction

This proposal introduces an opt-in protocol, `PropertyInitializable`, which provides two new init methods:

- failable init from a collections of extensible, typesafe keypath-value _Property_ objects
- non-failable init to clone from another instance, mutating select properties

The name “compositional init” means that this proposal allows the state of an object or struct to be assembled _compositionally_ from sets of properties (including another instance). Compositional initialization allows mutations to be encapsulated in a clear, type-safe way.

This proposal addresses the problems that motivated Matthew Johnson's excellent proposal, [SE-0018](https://github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md), but in a different way. Hopefully compositional init can serve as the implementation of SE-0018, which unfortunately got tabled due lack of ABI impact.

I initially wrote this proposal in 2018 based on Swift 4. I have reviewed the changes and proposals since then and it does not seem like there has been anything that would make this proposal unnecessary, please correct me however if I missed something.

From that review of past proposals, I find that this proposal may also address the desires expressed in the Swift Evolution discussion thread ["Record initialization and destructuring syntax"](https://forums.swift.org/t/record-initialization-and-destructuring-syntax/16631). I do not see any follow-up proposal for that, so hopefully this might help with that too.

I have a mostly working implementation made in the Swift 5 Playground [here](https://github.com/gistya/properties/blob/master/properties.swift).

## Motivation

Immutability carries many benefits including thread safety, simplification of state management, and improved code comprehensibility. It’s what makes functional programming so functional, which helps create unit-testable code.

However, in Swift 5, the benefits of immutability include neither:

(1) - "ease of making a copy that differs from the original in a subset of its properties — without lots of boilerplate,” nor (more generally),

(2) - "initializing an object from a collection or set of collections of its properties in one line of code."

The desire for no boilerplate and greater flexibility when initializing and cloning immutable types motivated this proposal.

### Use Cases

A growing movement exists to [use immutable models to handle data responses from the web in Swift applications](https://academy.realm.io/posts/slug-peter-livesey-managing-consistency-immutable-models/).

This proposal was inspired by mocking a web service in Swift, where we had to simulate the server’s responses by changing a few properties of an immutable data model object from a canonical example. However, in addition to satisfying that one need, I found that this style of initialization allows for many other useful patterns that simplify code and improve clarity.

### Detail of the Motivation

Chris Lattner’s SE-0018 proposal notes that in current solutions for (1), “initialization scales with M x N complexity (M members, N initializers).” I call this the “boilerplate cost” — measured on the “big B” scale. Indeed, [one advised workaround](https://stackoverflow.com/questions/38331277/how-to-copy-a-struct-and-modify-one-of-its-properties-at-the-same-time) for (1) involves going from B(M\*N) down to B(2M), where M is the number of different properties to be supported for mutation during cloning.

**Compositional Init** , on the other hand, provides B(0) for copying an immutable object while changing some arbitrary selection of its properties, and also provides a B(0) solution for problem (2).

### How Other Languages Have Solved (1)

Other languages have good solutions for (1) that are similar to compositional init, but none seem to solve (2) the way CI can.

Some examples of static, typesafe, functional languages that allow the initialization of a new instance via cloning with property overrides:

- Haskell’s’ [default values in records](https://wiki.haskell.org/Default_values_in_records): `newRecord = fooDefault { quux = 42 }` makes a clone where `quux` is overridden but the `bar` and `baz` properties are copied from `fooDefault`
- OCaml’s [functional updates](https://realworldocaml.org/v1/en/html/records.html#functional-updates): `let newRecord foo = { foo with quux = 42 };;`
- A Successor-ML proposal for [functional record update proposal](http://sml-family.org/successor-ml/OldSuccessorMLWiki/Functional_record_extension_and_row_capture.html) suggests: `foo {defaults where quux=42}`
- Elm features [updating records](http://elm-lang.org/docs/records#updating-records): `newRecord = { foo | quux = 42 }`

Dynamic languages have been slower to embrace immutability, but support for this concept is growing:

- An ECMAScript 7 proposal for [object spread initializer](https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md) suggests: `let fooWithOverrides = { quux: 42 , ...foo };` etc.
- An ECMAScript 6 [library for clone + mutate](https://www.npmjs.com/package/transmutable)

## Proposed solution

Compositional init solves both (1) and (2) by adding simple, clear, Swifty syntax for the initializing an immutable instance from a set of typesafe properties and an optional clone argument. Because this proposal is based purely upon Swift 4/5’s wonderful KeyPath and Mirror types, we get all the type safety and access restriction guarantees that they already carry.

Traditional memberwise init:

```
let fool: Foo = Foo(bar: “one”, baz: 1.0, quux: nil)

```

Compositional init cloning `fool` and mutating its `quux` property:

```
let food: Foo = Foo(clone: fool, mutating: \.quux => 42)

```

Compositional init failably initializing `foom` from an array of properties:

```
let properties: [PartialProperty<Foo>] = 
[
   \.bar => “two”, 
   \.baz => 2.0, 
   \.quux => nil
]

let foom: Foo? = Foo(properties)

```

Compositional init failably initializing `foom` from variadic property arguments:

```
let foom: Foo? = Foo(\.bar => “two”, \.baz => 2.0, \.quux => nil)

```

As a result of being based on `WritableKeyPath<Root, Value>`, the declaration `\Foo.bar => “two”` will fail to compile if the property `Foo.bar` is any of the following:

- not accessible in the current scope
- not writable in the current scope
- not the same type as the value being paired with it
- non-existent

## Detailed design

This proposal introduces the following protocols:

- AnyPropertyProtocol
- PartialPropertyProtocol
- PropertyProtocol
- PropertyInitializable

Accompanying these, we introduce implementations:

- AnyProperty
- PartialProperty
- Property\<Root, Value\>

This proposal introduces the “partially type-erasing lazy assignment operator” `=>`, which returns a `PartialProperty<Root, Value>` from a `WritableKeyPath<Root,Value>` on the left side, and on the right, an `@autoclosure @escaping` that can accept either:

- a `Value` object, or
- a function returning `Value` that will be lazily executed only at init.

## Source compatibility

Aside from any naming collisions (sorry), this proposal should have zero effect on source code compatibility.

## Effect on ABI stability

The initial PR for this proposal should not impact ABI stability, as far as I can tell.

## Effect on API resilience

Compositional init should play nice, but I will leave it to the experts.

## Alternatives considered

One alternative is to simply avoid immutable “set once at init” style properties, and instead use `var` for any properties you might need to change. The pattern is then to “immutable-ize” the root type by using `let` at instantiation, as in:

```
struct Foo {
    var bar: String 
    var baz: Double
    var quux: Int?
}

let fool = Foo(bar: “one”, baz: 1.0, quux: nil) // hah! can’t change me now!

var food = fool 
food.quux = 42
let foom = food // immutable once again.

```

That workaround is not great because there is nothing to prevent mistakes or abuses.

As well there was discussion on the aforementioned thread on destructuring, to which you may refer.

## Discussion

I created a mostly working playground implementation of this under Swift 5, which can be found on github [here](https://github.com/gistya/properties/blob/master/properties.swift).

There are some limitations in the way Swift 5 handles WritableKeyPath. They cannot be used to write to a property before it is initialized, sadly. If they could be, that would really improve the flexibility of how this can be used. As it stands, this limitation means that any variable which you want to be able to initialize from a keypath-value pair (a Property) must be a `var` and must have a default value or an initializer that gives it one.

Ideally, WritableKeyPaths could be used to initialize `let` variable or a `priave(set) var`, since the type adopting PropertyInitializable inherits an init method that, it stands to reason, should have access to do so. However, the way the compiler decides if a keypath can be considered "Writable" does not consider which scope the keypath will actually be used in when the writing finally takes place, or when it will take place (e.g. at init time, at which point a `let` variable could still be writable, technically speaking).

Any tips from the compiler gurus on how this could be enhanced would be appreciated. Perhaps we would need something like an "InitializableKeyPath" indicating that the variable can be set only at init time, by an init function within the type, using such a KeyPath. (Note: WritableKeyPath did work with an uninitialized `private (set) var` in Swift 4, but not in Swift 5.)

However if WritableKeyPaths to `let` variables cannot feasibly be used even at init time, then we could consider that since compositional init is opt-in at the type level anyway, we might as well consider it opt-in at the property level, too, by making it a var.

I look forward to everyone's thoughts on this. Thanks

---

<div class="post-metadata">

**Author:** ![Alejandro](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alejandro/32/46197_2.png) [@Alejandro](https://forums.swift.org/u/Alejandro)\
**Post date:** [October 4, 2019, 8:29pm UTC](https://forums.swift.org/t/compositional-initialization/29535/2 "2019-10-04T20:29:58Z")

</div>

> [@vitamin](#):
>
> This proposal addresses the problems that motivated Chris Lattner’s excellent proposal, [SE-0018](https://github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md)

Just FYI, this proposal was written by @anandabits. Chris was the review manager.

---

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 4, 2019, 8:31pm UTC](https://forums.swift.org/t/compositional-initialization/29535/3 "2019-10-04T20:31:02Z")

</div>

Ah, thank you, I'll update the main post.

---

<div class="post-metadata">

**Author:** ![DeFrenZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/defrenz/32/827_2.png) [@DeFrenZ](https://forums.swift.org/u/DeFrenZ)\
**Post date:** [October 4, 2019, 8:35pm UTC](https://forums.swift.org/t/compositional-initialization/29535/4 "2019-10-04T20:35:07Z")

</div>

> [@vitamin](#):
>
> One alternative is to simply avoid immutable “set once at init” style properties, and instead use `var` for any properties you might need to change. The pattern is then to “immutable-ize” the root type by using `let` at instantiation, as in:

```swift
struct Foo {
  let bar: String 
  let baz: Double
  let quux: Int?
} // hah! can't change me now!

let fool = Foo(bar: "none", baz: 1.0, quux: nil)
let foom = Foo(bar: fool.bar, baz: fool.baz, quux: 42) // immutable once again.

```

Personally I think that having `let` properties in `struct`s might be necessary only when the type doesn't follow value semantics, as you might want to force changes to go through the `init` again, or other `mutating` methods.

* * *

I think that the highlighted use-cases can be mostly solved with the famous `extension Any { func with ...` and, if even needed, some syntax for easier currying (for the `init`s here)

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [October 4, 2019, 8:37pm UTC](https://forums.swift.org/t/compositional-initialization/29535/5 "2019-10-04T20:37:35Z")

</div>

You can get pretty close to the stated goals with just a global function:

```swift
func with<T>(_ value: T, update: (inout T) -> Void) -> T {
  var newValue = value
  update(&newValue)
  return newValue
}

let fool: Foo = Foo(bar: “one”, baz: 1.0, quux: nil)

let food = with(fool) { $0.quux = 42 }

```

Value semantics gives you all the same stated goals of immutability while still allowing for efficient local state updates.

---

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 4, 2019, 8:45pm UTC](https://forums.swift.org/t/compositional-initialization/29535/6 "2019-10-04T20:45:05Z")

</div>

Well, the global function is very nice, however it does not allow for the core idea of this proposal, which is initialization via an array _composed of_ properties, e.g.:

```swift
let properties: [PartialProperty<Foo>] = 
[
   \.bar => “two”, 
   \.baz => 2.0, 
   \.quux => nil
]

let foom: Foo? = Foo(properties)

```

Being able to assemble a set of properties for an object in a type-safe way, then being able to use that set of properties to create a new instance or clone an existing instance, is the key idea here. To me it seemed like a nice evolution from keypaths. Whether that's seen as worthy of inclusion to the language, that's the question.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [October 4, 2019, 8:46pm UTC](https://forums.swift.org/t/compositional-initialization/29535/7 "2019-10-04T20:46:10Z")

</div>

Having a way to assemble a value from a collection of keypath-value pairs would be interesting, I agree. I think that belongs in the same general bucket of reflection mechanisms as things like [StoredPropertyIterable](https://forums.swift.org/t/storedpropertyiterable/19218).

---

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 4, 2019, 8:55pm UTC](https://forums.swift.org/t/compositional-initialization/29535/8 "2019-10-04T20:55:14Z")

</div>

@Joe_Groff wrote:

> Having a way to assemble a value from a collection of keypath-value pairs would be interesting, I agree. I think that belongs in the same general bucket of reflection mechanisms as things like [StoredPropertyIterable](https://forums.swift.org/t/storedpropertyiterable/19218).

You're right, that proposal is definitely in the same "reflection" bucket. My playground implementation linked above relies on the reflection features from Swift 4, but having some enhanced capabilities like those mentioned in StoredPropertyIterable would be great.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 4, 2019, 11:35pm UTC](https://forums.swift.org/t/compositional-initialization/29535/9 "2019-10-04T23:35:18Z")

</div>

Another option that (I think?) accomplishes the same goal would be a generated `clone` function with the current properties as default parameters. Something similar to how you do a [copy in Kotlin](https://kotlinlang.org/docs/reference/data-classes.html#copying)

e.g. in Swift it could look like this:

```swift
struct ClonableType: Clonable {
    var aString: String
    var anInt: Int

    // could/should be generated
    func clone(aString: String = aString, anInt: Int = anInt) -> Self {
        return Self.init(aString: aString, anInt: anInt)
    }
}

let initial = ClonableType(aString: "Indexed", anInt: 0)
let second = initial.clone(anInt: 1)

```

This feels much more natural to me as it mirrors the init rather than introducing something new, and skips the extra steps necessary for Key Paths.. It also would follow the existing rules for initializers, which means it could also be added to classes without avoiding expected init behavior.

There are of course several issues, the biggest of which is that clone function isn't currently possible in Swift since default parameters have to be defined at compile time, though my guess is this specific case wouldn't violate the likely reasons for that restriction. It's also unclear what should be generated when there are multiple initializers.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [October 5, 2019, 12:33am UTC](https://forums.swift.org/t/compositional-initialization/29535/10 "2019-10-05T00:33:23Z")

</div>

In case anyone is interested, the latest draft of my thinking on Memberwise initialization can be found here: [Explicit Memberwise Initializers](https://forums.swift.org/t/explicit-memberwise-initializers/22893).

---

<div class="post-metadata">

**Author:** ![typesanitizer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/typesanitizer/32/8661_2.png) [@typesanitizer](https://forums.swift.org/u/typesanitizer)\
**Post date:** [October 5, 2019, 1:06am UTC](https://forums.swift.org/t/compositional-initialization/29535/11 "2019-10-05T01:06:13Z")

</div>

Not taking away from the content of your proposal, but the Elm example should fall under "static, typesafe, functional languages", not "Dynamic languages".

---

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 5, 2019, 5:39am UTC](https://forums.swift.org/t/compositional-initialization/29535/12 "2019-10-05T05:39:09Z")

</div>

> [@typesanitizer](#):
>
> Not taking away from the content of your proposal, but the Elm example should fall under "static, typesafe, functional languages", not "Dynamic languages".

Fixed, thanks.

---

<div class="post-metadata">

**Author:** ![vitamin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vitamin/32/11098_2.png) [@vitamin](https://forums.swift.org/u/vitamin)\
**Post date:** [October 5, 2019, 10:16am UTC](https://forums.swift.org/t/compositional-initialization/29535/13 "2019-10-05T10:16:45Z")

</div>

> [@GetSwifty](#):
>
> Another option that (I think?) accomplishes the same goal would be a generated `clone` function with the current properties as default parameters

That's a fine approach to cloning.

However, I'm not offering this proposal as an alternative to something like that, nor is this meant as an alternative to the great [Explicit Memberwise Initializers](https://forums.swift.org/t/explicit-memberwise-initializers/22893) proposal of Matthew Johnson.

Rather, the point of Compositional Initialization is **to allow an object to be composed before it is initialized** from a set of type-safe keypath-value pairs.

In the current form of this proposal, these pairings take the form of `Property<Root,Value>` objects.

You can look at this proposal as building upon the foundation laid by **KeyPath**.

See, in Swift 4 we got KeyPath, but we did not get any easy way to use a KeyPath to initialize an object or to make a clone mutated at some property—nor did we get a type like `Property` allowing the developer to pair a KeyPath with a Value.

Given that it seems natural to pair KeyPaths and Values, once you have a set of these pairs, it seems natural then to make an object from them.

So this proposal offers a simple way to do that.

Here is a working example from the Swift 5 Playground linked in the top post:

```swift
struct Customer: PropertyInitializable {    
    var name: String = ""
    var zipcode: Int = 0
    var addressLine1: String = ""
    var addressLine2: String = ""
    var addressLine3: String = ""
    
    /// Necessary because of the fact WritableKeyPath cannot currently be used
    /// to actually initialize a variable. It must have a value first. 
    internal static var _blank: Customer {
        get { return Customer() }
    }
}

let dataFromTestWebResponse = [PartialProperty<Customer>]() 
    + (\.name, "Steve Jobs") 
    + (\.zipcode, 97202) 
    + (\.addressLine1, "Reed College")
    + (\.addressLine2, "3203 SE Woodstock Blvd")
    + (\.addressLine3, "Box #121")

if let customer: Customer = Customer(dataFromTestWebResponse) {
    print(customer)
} else {
    print("Data is missing.")
}

```

As this example shows, we can create a type-safe array of properties for an object using nothing but tuples. (This relies on a custom infix function `+` defined on an extension to Array; please see the linked Playground page for the full source.) We can then try to initialize the object from that array.

The failable `init` method is defined in `PropertyInitializable` protocol as:

```swift
init?(_ properties: [PartialProperty<Self>])

```

The elements of the `dataFromTestWebResponse` array are of the type `PartialProperty<Customer>`.

At first glance, that array might not seem to be fully type-safe.

However, the underlying objects are type-safe `Property<Customer,Value>` objects that have been partially type-erased so they can exist within the same array. This is necessary because they differ as to the type of `Value`—`zipcode` is an `Int` but the rest are `String`. (Note: this naming convention follows exactly from Swift's existing `PartialKeyPath` and `KeyPath`.)

In this way, you can "compose" the properties of an object in a completely type-safe way prior to initialization, and then initialize the object from those properties with minimal boilerplate.

For example we might do:

```swift
let reedieData = [PartialProperty<Customer>]()
    + (\.zipcode, 97202) 
    + (\.addressLine1, "Reed College")
    + (\.addressLine2, "3203 SE Woodstock Blvd")

let studentBoxAssignments: [(String, Int)] = [("Steve Jobs", 121), ("The Woz", 314)]

var customers = [Customer]()

for (name, box) in studentBoxAssignments {
    let data = reedieData + (\.name, name) + (\.addressLine3, "Box #\(box)")
    if let customer: Customer = Customer(data) {
        customers += [customer]
    } else {
        print("Data is missing.")
    }
}

print(customers)

```

By saying this is completely type-safe, I mean, if we put `"97202"` as a string then we'll get a compiler error, since the proper type is inferred from the KeyPath.

Now, let me address the reasoning behind the `=>` syntax, from the example in the original post:

```swift
let properties: [PartialProperty<Foo>] = 
[
   \.bar => “two”, 
   \.baz => 2.0, 
   \.quux => nil
]

```

Frankly, this is just a simple alternative to using the tuples syntax from the examples above. By defining `=>` as a custom infix operator, we can do away with the parentheses around each key-value pair.

If `=>` seems un-Swifty, I'd love to hear a better suggestion. [Swift's custom operator syntax](https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418) does not permit the use of `:` when defining a custom infix operator here; that would make this a Dictionary.

Speaking of Dictionaries, I originally tried using Dictionary instead of Array, since it seemed like a more natural place to store keypath-value pairs. However, I found using a Dictionary for this purpose to be frought with problems. Let me know if you want the details on why that did not seem feasible.

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [October 5, 2019, 5:32pm UTC](https://forums.swift.org/t/compositional-initialization/29535/14 "2019-10-05T17:32:51Z")

</div>

One unfortunate side-effect of the proposed design is that by partially type-erasing the property values in your wrappers, and then incurring a heap allocation by storing them in an array, the creation of this set of properties is probably going to have significantly worse performance than would simply creating the instance of the type itself, at least for many value types.

Bouncing off from @Joe_Groff's idea above, could something like this be achieved by sequencing closures with an `inout` argument instead? Instead of inventing entirely new concepts around keypath/value pairs, your example above could also be expressed as:

```swift
let propertySetter = { (inout Foo) -> () in
  $0.bar = "two"
  $0.baz = 2.0
  $0.quux = nil
}

```

And the addition of property arrays you were doing could be achieved by applying multiple closures in sequence. This would still allow you to "compose an object before it is initialized"; it's just composed as a sequence of closures instead of as "data". But I think that's more natural Swift. And since there has already been some work done to bridge keypaths and closures, perhaps that could even be extended further to make this more elegant.

---

<div class="post-metadata">

**Author:** ![CTMacUser](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ctmacuser/32/1802_2.png) [@CTMacUser](https://forums.swift.org/u/CTMacUser)\
**Post date:** [October 5, 2019, 9:05pm UTC](https://forums.swift.org/t/compositional-initialization/29535/15 "2019-10-05T21:05:49Z")

</div>

Could `PropertyInitializable.init(_: )` be generalized to take a `Sequence` of `PartialProperty`?

---

<div class="post-metadata">

**Author:** ![DeFrenZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/defrenz/32/827_2.png) [@DeFrenZ](https://forums.swift.org/u/DeFrenZ)\
**Post date:** [October 5, 2019, 10:22pm UTC](https://forums.swift.org/t/compositional-initialization/29535/16 "2019-10-05T22:22:55Z")

</div>

The issue with this is that to use these closures you need an already existing `Foo`.  
If there were something like an `init` modifier for arguments that says that it’s not an initialised object, so you can only set properties but not read them, then it would work. But you’d still have the issue that — since it’s composable — you don’t have a good way to know when an object is completely initialised. Or even worse with `class`es to know if `super.init` was called...  
And it also can probably live only in the same module as the type unless you call another `init` of the type

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [October 5, 2019, 10:27pm UTC](https://forums.swift.org/t/compositional-initialization/29535/17 "2019-10-05T22:27:51Z")

</div>

> [@DeFrenZ](#):
>
> The issue with this is that to use these closures you need an already existing `Foo` .

I'm aware of that, and it's a limitation of the original poster's own proposal, too:

> [@vitamin](#):
>
> As it stands, this limitation means that any variable which you want to be able to initialize from a keypath-value pair (a Property) must be a `var` and must have a default value or an initializer that gives it one.

I'm not suggesting that closures **alone** would solve the problem of compositional initialization, but nor does an array of keypath/value pairs, because the latter is just a more restricted form of the former. My only point is that if that problem is going to be tackled, I think a solution that composes closures that somehow can operate on a partially-initialized value is a better approach than creating entirely new concepts and collections of type-erased keypath/value pairs.

---

<div class="post-metadata">

**Author:** ![DeFrenZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/defrenz/32/827_2.png) [@DeFrenZ](https://forums.swift.org/u/DeFrenZ)\
**Post date:** [October 5, 2019, 11:05pm UTC](https://forums.swift.org/t/compositional-initialization/29535/19 "2019-10-05T23:05:51Z")

</div>

> [@allevato](#):
>
> it's a limitation of the original poster's own proposal, too

I missed that bit, didn’t know that you can’t use key paths for initialising! Though that could be something that changes as part of this proposal, or a spin-off of it

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [October 6, 2019, 5:30am UTC](https://forums.swift.org/t/compositional-initialization/29535/20 "2019-10-06T05:30:05Z")

</div>

Unless I’m missing something, this sounds rather like an [unconventional] implementation of the builder pattern. The traditional ‘downside’ of builders is that they’re not built into the language - it’s just an _additional_ class you manually define. That can be a lot of tedious work, though. Optimising away that manual labour is appealing. But maybe there’s a more direct if ‘boring’ way to do so… in the spirit of just exploring alternatives for due diligence if nothing else, how about something like a `Buildable` protocol which can be used like:

```swift
struct Example: Buildable {
  let foo: String
  let bar: Int = 0
  let baz: URL?
}

// The above, through the magic of compiler-synthesised methods, becomes essentially:

struct Example: Buildable {
  let foo: String
  let bar: Int = 0
  let baz: URL?

  func asTemplate() -> Builder {
    return Builder(basedOn: self)
  }

  struct Builder { // Or ‘Template’, maybe?
    var foo: String
    var bar: Int
    var baz: URL?

    internal init(basedOn template: Example) {
      self.foo = template.foo
      self.bar = template.bar
      self.baz = template.baz
    }

    func setFoo(foo: String) -> Self {
       self.foo = foo
       return self
    }

    … etc …

    func init() -> Example {
      return Example(foo: self.foo, bar: self.bar, baz: self.baz)
    }
  }
}

// In use:
let standard: Example = …
let variant = standard.asTemplate().setBar(11).init()

```

It’s possible to expand on that to also support the traditional build-from-scratch builder use (though I’m not sure how one can write it in a way that avoids the annoying need to use `try` somewhere during construction, within the capabilities of Swift 5.1).

I’m not saying it’s better, just throwing it out there as an alternative approach.

It does seem to me that this would provide essentially the same functionality - the difference seems to be essentially just the subjective aspects - aesthetics, ergonomics, etc. It seems like it’d make simple cases a bit more verbose, but for complex cases - e.g. when you’re performing the build across significant code and/or time - it seems like it’d be equivalent in brevity.

It has the benefit of being more familiar to a large number of people (e.g. those coming from Java, C++, etc) and of relying less on complex language features (e.g. KeyPaths).

While it’s merely as type-safe as this pitch’s approach, it is IMO a bit safer in practical terms because you don’t have KeyPaths floating around detached from things.

Re. mutability, it avoids any irony from otherwise having to keep around a potentially mutable ‘template’ instance, since you’d only need to keep around the Builder instance itself, and as a distinct type it can’t be accidentally used by code unrelated to the building process itself.

…

That all said, I’m not sure any of this is the right approach… for value types, the existing `var` and `let` work just fine IMHO for ensuring that your immutable values truly are immutable (i.e. no-one else can have a `var` reference to them behind your back - that’s the whole point of _value_ types). And I assume the compiler makes the make-mutable-copy-mutate-make-immutable-copy into the optimal, literally just a copy & subsequent assignments under the cover.

For reference types, I wonder if (a) this all wouldn’t be better addressed through something like Rust-style exclusive mutability control, to get essentially the same guarantees as for value types, but also (b) whether you really can have a _generic_ way to ‘clone’ objects like this, given the potentially complex semantics of reference types. e.g. not every element of an object’s state is necessarily exposed to the type’s users, so would presumably _have_ to be implicitly cloned exactly, _but_ reference types frequently can’t support that because they can have uniqueness constraints on some or all that internal state… thus why I feel that, if nothing else, this functionality has to be both opt-in on a per-type basis _and_ overriddable if the default implementation is insufficient.

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [October 6, 2019, 5:38am UTC](https://forums.swift.org/t/compositional-initialization/29535/21 "2019-10-06T05:38:20Z")

</div>

Nitpick, albeit a worthy one IMO: `=>` looks like a rightward-pointing arrow, so it’s going the wrong direction, since assignment is from rvalues to lvalues. `<=` would be the correct direction, but is of course already taken for the ‘less than or equal to’ operator. So you’d have to consider variants like `<-` or `<~` etc, but probably no matter what you pick you’ll earn the wrath of at least some library authors that have already claimed those character sequences for their own custom operators. 😛

[Next page](https://forums.swift.org/t/compositional-initialization/29535.md?page=2)
