<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I think this idea scratches at the surface of a problem with initializers that definitely merits some attention. Boilerplate is common in initializers which can lead to types that don’t allow as much flexibility to callers as might be desirable. </div><div class=""><br class=""></div><div class="">More importantly, it can also lead to “initialized” instances that are not fully or properly configured, (implicitly unwrapped?) optional members, and mutability that shouldn’t be necessary past the initial configuration stage of the instance. For example, if a type provides a family of initializers, but also has several members which are intended to be initialized / configured directly by callers a developer could choose to avoid the boilerplate by declaring the additional members as as an implicitly unwrapped optional var members. No doubt this is a bad idea. If the caller does not initialize all of the additional members there is a bomb waiting to go off. Furthermore, there is the potential for mutation after initialization that may not be expected or intended. By requiring a nontrivial amount of boilerplate to avoid this situation the language is unintentionally nudging lazy developers towards bad practices like this.</div><div class=""><br class=""></div><div class="">Let's start with the current proposal but go a bit further and see how much boilerplate can be removed. The type information is already known from the property declaration, and furthermore a default may also be available in the property declaration.</div><div class=""><br class=""></div><div class="">struct Foo {<br class=""> let bar: String<br class=""> let bas: Int = 1</div><div class=""> let bat: Float = 0</div><div class=""> let bax: String = “default"<br class=""> let baz: Double</div><div class=""> </div><div class=""> // self.bar is known to be a String but does not have a default value so it must be provided by the caller </div><div class=""> // self.bas is known to be an Int and implicitly has a default value of 1 specified by the property </div><div class=""> // so it does not need to be provided by the caller</div><div class=""> // self.bat is known to be a Float, but the default is overridden to be 1 instead of 0</div><div class=""> // external labels are provided that correspond to the names of the properties</div><div class=""> init(self.bar, self.bas, self.bat = 1) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>// the initializer does not receive a value for baz and the property does not provide a default </div><div class=""> // so it must be initialized here before the first phase of initialization is complete</div><div class=""> // if all stored properties had received values through parameters or through property defaults </div><div class=""> // the first phase of initialization would have already been completed when the body of the initializer was entered</div><div class=""> self.baz = someComputedDoubleValue()</div><div class=""> // now all stored properties have been initialized so the first phase of initialization is complete</div><div class=""> }<br class=""><div dir="ltr" class=""><div class="">}</div><div class=""><br class=""></div><div class="">This structure allows us to remove the boilerplate of the property type and default value. </div><div class=""><br class=""></div><div class="">Given the significant difference from regular function parameters, it may make sense to set these apart syntactically in some way, although I am not sure what would make the most sense. For example, we could just have a second parameter tuple in the initializer declaration which represents the “member parameters” to the initializer like this:</div><div class=""><br class=""></div><div class="">init(foo: Int)(self.bar, self.bas, self.bat = 1)</div><div class=""><br class=""></div><div class="">or a vertical pipe like this:</div><div class=""><br class=""></div><div class="">init(foo: Int | self.bar, self.bas, self.bat = 1)</div><div class=""><br class=""></div><div class="">Setting these “member parameters” apart syntactically could also facilitate additional mechanisms to further reduce boilerplate if we find that the same group of “member parameters" exist for several different initializers in the same type. For example, it might become possible to implement a memberwise initializer like this:</div><div class=""><br class=""></div><div class="">// @automembers expands to match all stored properties</div><div class="">init()(@automembers) {}</div><div class=""><br class=""></div></div></div><div class="">At this point we have eliminated virtually all of the boilerplate, encouraging developers to use concise *and* safe, yet still flexible initialization strategies. </div><div class=""><br class=""></div><div class="">Matthew</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 4, 2015, at 9:05 PM, Dan Appel <<a href="mailto:dan.appel00@gmail.com" class="">dan.appel00@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I'm not sure how I feel about this, but in either case, why limit it to default parameters? It's useful in other situations, too.<div class=""><br class=""></div><div class="">Take this for example:</div><div class="">struct Foo {</div><div class=""> let bar: String</div><div class=""> let bas: Int</div><div class=""> let baz: Double</div><div class=""> init(self.bar: String, self.bas: Int, bax: Int) {</div><div class=""> self.baz = Double(bax)</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">where the need to say</div><div class=""><br class=""></div><div class="">self.bar = bar</div><div class="">self.bas = bas</div><div class=""><br class=""></div><div class="">is now avoided.</div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Fri, Dec 4, 2015 at 3:16 PM Tal Atlas <<a href="mailto:me@tal.by" class="">me@tal.by</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">There’s lots of boilerplate of initializing structs with stored properties and initializer parameters. I’d like to create a syntax for alleviating that in the 90% case.<div class=""><br class=""></div><div class="">```swift</div><div class=""><div class="">struct Foo {</div><div class=""> let bar: String</div><div class=""> let baz: Int</div><div class=""><br class=""></div><div class=""> init(self.bar: String = "default", counter self.baz: Int) {</div><div class=""> }</div><div class="">}</div></div><div class="">```</div><div class=""><br class=""></div><div class="">This would be identical to:</div><div class="">```swift</div><div class=""><div class="">struct Foo {</div><div class=""> let bar: String</div><div class=""> let baz: Int</div><div class=""><br class=""></div><div class=""> init(bar: String = "default", counter baz: Int) {</div><div class=""> self.bar = bar</div><div class=""> self.baz = baz</div><div class=""> }</div><div class="">}</div></div><div class="">```</div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=4Q3dO0ELn940F2HNV6NWP3n6-2BFmLgXvEeytAtbr-2BgeDjXIPyyMbjq9G0JfeQzz9WnsbJBYDj0ld8xKG0k9Pe-2B6zZcWO1GEZDkVL-2FCGOPH9cApFGwawJSOc83rktiBCKxaRdcy1D8mKgzhjO2T-2FKfoRdWdMrPChURl7ayI3aW6YmNT4UeczuHWZ4IFNjFSE-2BnNyQTmxEuFMXWox6-2FrxmQ7zFi2iORpYT5sAsW4IAphgM-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important" class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div><div dir="ltr" class="">-- <br class=""></div><div dir="ltr" class=""><div class=""><div class="">Dan Appel<br class=""></div></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=eLFMrKDT8iBxZ-2Fbnk-2BZqvSchNN-2FvYXdceA0T7VxwkAeAku5CIgbF1ILy7puwEpQNdlLinipU-2BUdsq1yoyMN-2BiSIafNN2MzaYl1E3IkunVVNGwnS0TDXZ0F-2F1dlL6xm1DYGQMb2ikgzN4JPpfLiHmSKUzbDPLSekJWZ0Rco0dzMxlwyIH-2FIWY0r-2B0S5FTzeoRALrC17snC5etZq1j-2Bx43MeSfh9W-2FoNKbzAugAgMcGHQ-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>