[swift-evolution] Rules for structs default/memberwise initializers
Matthew Johnson
matthew at anandabits.com
Wed Feb 15 09:57:29 CST 2017
Hi Dimitri,
You may be interested in taking a look at a proposal I introduced about a year ago which was deferred. Memberwise initialization is a topic we intend to revisit eventually. This may happen in phase 2 of the Swift 4 effort, or may not happen until Swift 5.
https://github.com/apple/swift-evolution/blob/master/proposals/0018-flexible-memberwise-initialization.md
Matthew
> On Feb 15, 2017, at 9:38 AM, Dimitri Racordon via swift-evolution <swift-evolution at swift.org> wrote:
>
> Hello community!
>
> While writing a Swift introduction tutorial for students, I’ve been stumbling upon the rules for struct default and memberwise initializers.
> I failed to find explanations in Apple’s language guide, but as far as I could observe, I think the rules don’t fit interesting use-cases.
>
> Here are the cases that I was able to identify (I hope you don’t mind millennials and their obligatory Pokemon references):
>
> First, as documented in Apple’s guide, structs that doesn’t define any initializer and have no default values receive a memberwise initializer:
>
> typealias Species = (number: Int, name: String)
>
> struct Pokemon {
> let species: Species
> var level: Int
> var nickname: String
> }
>
> let bulby = Pokemon(species: (001, "Bulbasaur"), level: 1, nickname: "bulby")
>
> Structs that define a default value for all their properties receive a default initializer:
>
> struct Pokemon {
> let species: Species = (001, "Bulbasaur")
> var level: Int = 1
> var nickname: String = "bulby"
> }
>
> let bulby = Pokemon()
>
> Now digging a bit deeper, I noticed that they also seem to receive an initializer for their non-constant properties:
>
> let bulby = Pokemon(level: 1, nickname: "bulby")
>
> If no value is provided for one (or several) of its variable properties, they receives an initializer for all their variable properties:
>
> struct Pokemon {
> let species: Species = (001, "Bulbasaur")
> var level: Int = 1
> var nickname: String
> }
>
> let bulby = Pokemon(level: 1, nickname: "bulby")
>
> Finally, if they're given a default value for their variable properties but not for their constant properties, they receive the full memberwise initializer only:
>
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
> }
>
> let bulby = Pokemon(species: (001, "Bulbasaur"), level: 1, nickname: "bulby")
>
> If the two extreme cases sounds perfectly valid to me (no default value vs all default values), the mixed situations do not.
> In particular, it seems strange that a struct without a default value for its constant property, but one for all its variable properties receives the memberwise initializer only. I guess that would be a common “mixed situation” case, yet the provided initializer is actually useless.
>
> Receiving the full memberwise initializer is fine, but I would also expect to receive some kind of "partial memberwise” initializer for all properties (constants or variables) that are not defined:
>
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
> }
>
> let bulby = Pokemon(species: (001, "Bulbasaur”))
> print(bulby)
> // Prints "Pokemon(species: (1, "Bulbasaur"), level: 1, nickname: "bulby")"
>
> Besides, that would avoid some tedious initializer definitions. Indeed, If I want to get the desired result, I have to write this kind of initializer:
>
> struct Pokemon {
> let species: Species
> var level: Int = 1
> var nickname: String = "bulby"
>
> init(species: Species, level: Int? = nil, nickname: String? = nil) {
> self.species = species
>
> if level != nil {
> self.level = level!
> }
>
> if nickname != nil {
> self.nickname = nickname!
> }
> }
> }
>
> In addition to be rather wordy, it arguably destroys the purpose of defining a default value for variable properties in the first place, since imho this approach is clearer (unless maybe for some more complicated structs with multiple layers of initializer delegation):
>
> struct Pokemon {
> let species: Species
> var level: Int
> var nickname: String
>
> init(species: Species, level: Int = 1, nickname: String = "bulby") {
> self.species = species
> self.level = level
> self.nickname = nickname
> }
> }
>
> Thanks.
>
> Dimitri Racordon
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170215/34cac7d0/attachment.html>
More information about the swift-evolution
mailing list