[Pitch] Unifying init parameters with properties


(Ross O'Brien) #1

This is a common pattern for initialisers at the moment:

class Foo

{

let foo : String

let bar : String

let barCount : Int

let baz : Int

init(foo: String, bar: String, baz: Int)

{

self.foo = foo

self.bar = bar

self.baz = baz

barCount = bar.characters.count

}

}

This involves a lot of using 'self.'. For those who prefer not to use
'self.' explicitly everywhere, this is probably the main place it gets
used. It's a lot of boilerplate code.

How would it be if, like default variables, we could pack some of that
information into the argument tuple, and unify parameters with properties
immediately?

class Foo

{

let foo : String

let bar : String

let barCount : Int

let baz : Int

init(self.foo: String, self.bar: String, self.baz: Int)

{

barCount = bar.characters.count

}

}

Less boilerplate, more focus on the properties which need to be generated.

Thoughts?


(Ross O'Brien) #2

(re-added swift-evolution)

I would think so. It's an abbreviation of a given init function, so you
would call other self.init() or super.init() functions normally. Saves on
complication.

Alternatively, perhaps you could do this:

init(self.foo: String, super.bar: String, super.baz: Int)

as an abbreviation of
init(foo: String, bar: String, baz: Int)
{
    self.foo = foo
    super.init(bar: bar, baz: baz)
}

I think this would probably require allowing parameters to stay
re-orderable, though (in case super's init is "init(baz: Int, bar: String)"
).

···

On Thu, Apr 14, 2016 at 4:29 PM, Vladimir.S wrote:

+1. This will make our life easier, it is clear and explicit about the
result.

I assume that there must be a constrain : you can use in init(...) only
props introduced in the same class, not in parent class.

On 14.04.2016 17:32, Ross O'Brien via swift-evolution wrote:

init(self.foo: String, self.bar: String, self.baz: Int)

{

barCount = bar.characters.count

}

}

Less boilerplate, more focus on the properties which need to be generated.

Thoughts?


(Tino) #3

There has been a long debate about something similar:
[Proposal Draft] Flexible memberwise initialization <http://article.gmane.org/gmane.comp.lang.swift.evolution/727>

Afair there has been a general agreement that the current boilerplate is ugly, but all suggested alternatives had flaws as well (and init is already a complicated topic).
I'm quite sure a variant of your idea has been discussed, but didn't turn into a formal proposal.
Getting rid of a third of the boilerplate wouldn't be bad, and imho some additional characters could be saved if you skip the type declarations (this would also make it easier to refactor).
The linked proposal had less boilerplate, but much higher complexity.

Tino


(Vladimir) #4

Don't think idea with super.bar etc in init is good, as we should explicitly call super.init() with needed parameters.

So, I see this in such a way:

init(self.foo: String, bar: String, baz: Int)
   super.init(bar: bar, baz: baz)
   ...
}

The only way we can specify values for super.init in our init() is if special form of init will be introduced like:

init(self.foo: String, super.bar: String, super.baz: Int); //<-- see this semicolon

i.e. "emtpy" init. Probably it will be good to have such "empty" init, but the more important to have feature to init our own props in init header.

So +1 for props in init parameters, unsure about "empty" inits to support super.props.

> (re-added swift-evolution)
>
> I would think so. It's an abbreviation of a given init function, so you
> would call other self.init() or super.init() functions normally. Saves on
> complication.
>
> Alternatively, perhaps you could do this:
>
> init(self.foo: String, super.bar: String, super.baz: Int)
>
> as an abbreviation of
> init(foo: String, bar: String, baz: Int)
> {
> self.foo = foo
> super.init(bar: bar, baz: baz)
> }
>
> I think this would probably require allowing parameters to stay
> re-orderable, though (in case super's init is "init(baz: Int, bar: String)" ).

···

On 14.04.2016 18:40, Ross O'Brien wrote:
>
> On Thu, Apr 14, 2016 at 4:29 PM, Vladimir.S wrote:
>
> +1. This will make our life easier, it is clear and explicit about the
> result.
>
> I assume that there must be a constrain : you can use in init(...) only
> props introduced in the same class, not in parent class.
>
> On 14.04.2016 17:32, Ross O'Brien via swift-evolution wrote:
>
> init(self.foo: String, self.bar: String, self.baz: Int)
>
> {
>
> barCount = bar.characters.count
>
> }
>
> }
>
> Less boilerplate, more focus on the properties which need to be
> generated.
>
> Thoughts?
>


(Vladimir) #5

So I suggest to discuss some "middle" solution: not too complex, but that will improve our live. I believe this (in subject) proposal don't require a lot of changes in Swift, it seems more like sugar

Compiler "just" can replace

init (self.a: Int, self.b: String) {
   //...
}

to

init (a: Int, b: String) {
   self.a = a
   self.b = b
   //...
}

Yes, I understand that we can actually omit types for init(as each prop has its own type already) :

init (self.a, self.b, someOther: String) {
//...
}

But I'm afraid this brokes Swift parser a lot(so probably it is complex to implement this) and IMO init becomes not explicit on types of parameters when just looking at it(we need to go to each property to find this out). So I personally -1 for such skipping of types.

···

On 14.04.2016 18:41, Tino Heth via swift-evolution wrote:

There has been a long debate about something similar:
[Proposal Draft] Flexible memberwise initialization
<http://article.gmane.org/gmane.comp.lang.swift.evolution/727>

Afair there has been a general agreement that the current boilerplate is
ugly, but all suggested alternatives had flaws as well (and init is already
a complicated topic).
I'm quite sure a variant of your idea has been discussed, but didn't turn
into a formal proposal.
Getting rid of a third of the boilerplate wouldn't be bad, and imho some
additional characters could be saved if you skip the type declarations
(this would also make it easier to refactor).
The linked proposal had less boilerplate, but much higher complexity.

Tino

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution