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 
> <[email protected]> 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>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to