[swift-evolution] [Proposal Draft] Flexible memberwise initialization

David Owens II david at owensd.io
Tue Dec 22 00:08:32 CST 2015


I really like the idea and it’s something that’s extremely annoying to deal with today in Swift. My biggest concern is that the proposal, in its entirety, seems to really complicate the initialization rules.

Also, I don’t think it generates good API signatures. Take this example:

struct S {
	let s: String
	let i: Int

	// user declares:
	memberwise init() {}
	// compiler synthesizes:
	init(s: String, i: Int) {
		self.s = s
		self.i = i
	}
}

That is not a very descriptive API. It’s also not necessarily the case that your internal names are what you want exposed.

I would actually prefer the rule to simply be this: when an init() is modified by memberwise, the labelled parameters will be set. This lookup will try both the argument name and the parameter name, in that order, for reasons that become more clear with convenience inits described later.

So you would have this:

memberwise init(name s: String, value i: Int) {
    // autogenerated: self.s = s; self.i = i
}

This provides you all of the freedom that you may need:
Order of the APIs is explicitly controlled
API names of the members are not exposed if not desired, especially helpful for non-public members
Default values are handled naturally

Optionally, you could keep the default simply with this:

memberwise init {}

This would use the property names as the argument labels.

Another example:

memberwise init(name s: String, value i: Int = 12) {
    // autogenerated: self.s = s; self.i = i
}

And the usage is much nicer:

let s = S(name: "Happy")

Here’s a subclassing example:

class Animal {
    let type: String
    let numberOfLegs: Int
    
    memberwise init(type: String, numberOfLegs: Int) {
        /* generated */ self.type = type
        /* generated */ self.numberOfLegs = numberOfLegs
    }
}

class Dog: Animal {
    let name: String
    
    memberwise private init(type: String = "dog", numberOfLegs: Int = 4, n name: String) {
        /* generated */ self.name = name
        /* generated */ super.init(type: type, numberOfLegs: numberOfLegs);
    }
    
    memberwise convenience init(name: String) {
        /* generated */ self.init(type: "dog", numberOfLegs: 4, n: name)
    }
}

let d = Dog(name: "Fido")

The biggest thing about convenience inits is that the generation of the init needs to pull the defaults from the designated init. Also, for super.init(), it’s a straight label/name lookup for the designated init() only. Anything more fancy must be written by the user.

You also disallow private init, but that doesn’t need to happen with explicit members. That’s the beauty of giving the public API a real contract with names.

struct S {
    let s: String
    private let i: Int
    
    memberwise init(name s: String, value i: Int = 12) {
        /* generated */ self.s = s
        /* generated */ self.i = i
    }
}

Also, partial initialization could be possible, much like you proposed originally:

struct S {
    let s: String
    private let i: Int
    
    memberwise init(name s: String) {
        /* generated */ self.s = s
        self.i = s.utf8.count
    }
}

My concern is that this starts to be more complicated and magical. I’d actually cut this from the proposal.

The last change I would make is that if any property has an assignment in the declaration, it cannot be memberwise initialized.

struct S {
    let s: String
    let i: Int = 10
    
    memberwise init(name s: String) {
        /* generated */ self.s = s
    }
}

In the above, i will always be 10.

-David

> On Dec 21, 2015, at 11:32 AM, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I have completed a draft of the proposal I have been working on for flexible memberwise initialization.  I am really looking forward to your input and will be refining the proposal based on our discussion.
> 
> I am including a current snapshot of the proposal in this message.  I will keep the proposal up to date on Github at this link:
> 
> https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md <https://github.com/anandabits/swift-evolution/blob/flexible-memberwise-initialization/proposals/NNNN-flexible-memberwise-initialization.md>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151221/a3e7022e/attachment.html>


More information about the swift-evolution mailing list