<div dir="ltr">Lazy properties can&#39;t make use of parameters of the init() without storing them, and can&#39;t calculate parameters to be used in a super.init() (or decide which super.init() is called, if there are several to choose from). Part of the idea of the selfless function is to keep local lets/vars at local scope rather than type scope, and allow functions which perform calculations in an initialisation to be reusable.<div>Static functions can perform these calculations but can&#39;t set instance properties.</div><div>At the moment, for an init() to use initial parameters without storing them, all the code for setting properties has to be in the init; I don&#39;t think there&#39;s a way to break an init up into a sequence of smaller function calls, each dealing with a lower level of abstraction of the init. i.e. something like this:</div><div><br></div><div>init(&lt;initial arguments&gt;)</div><div>{</div><div>    initialiseColor(&lt;subset of arguments&gt;)</div><div>    initialiseSize(&lt;subset of arguments&gt;)</div><div>    initialiseFont(&lt;subset of arguments&gt;)</div><div>}</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 16, 2015 at 1:06 AM, Marc Knaup <span dir="ltr">&lt;<a href="mailto:marc@knaup.koeln" target="_blank">marc@knaup.koeln</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">In its current state with the initial example -1 from me for the proposal.<div><br></div><div>The example could easily be written like this:</div><div><br></div><div><div><font face="monospace, monospace">class FooView: UIView {</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    var property = 4</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init() {</font></div><div><span style="font-family:monospace,monospace">        super.init()</span><br></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init(frame: CGRect) {</font></div><div><font face="monospace, monospace">        super.init(frame)</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div><br></div><div>In cases where the initially value is computed in a complex way a closure can be used:</div><div><br></div><div><div><font face="monospace, monospace">class FooView: UIView {</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    var property: Int = {</font></div><div><font face="monospace, monospace">        // some complicated computation</font></div><div><font face="monospace, monospace">        return value</font></div><div><font face="monospace, monospace">    }()</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init() {</font></div><div><span style="font-family:monospace,monospace">        super.init()</span><br></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init(frame: CGRect) {</font></div><div><font face="monospace, monospace">        super.init(frame)</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>And that value could even delegate computation to static methods of the class.</div><div><br></div><div>In cases where the computation is even more complex and refers to other properties a <font face="monospace, monospace">lazy var</font> can be used, which even allows the value to refer to <font face="monospace, monospace">self</font>:</div><div><br></div><div><div><font face="monospace, monospace">class FooView: UIView {</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    private(set) lazy var property: Int = {</font></div><div><font face="monospace, monospace">        // some complicated computation which can use self</font></div><div><font face="monospace, monospace">        return value</font></div><div><font face="monospace, monospace">    }()</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init() {</font></div><div><span style="font-family:monospace,monospace">        super.init()</span><br></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">    init(frame: CGRect) {</font></div><div><font face="monospace, monospace">        super.init(frame)</font></div><div><font face="monospace, monospace">    }</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 16, 2015 at 1:30 AM, Charles Srstka via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><blockquote type="cite">On Dec 15, 2015, at 5:59 PM, Ross O&#39;Brien via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br></blockquote></div></div><div><blockquote type="cite"><br><div><div><div><div dir="ltr"><div style="font-size:13px">Hi all,</div><div style="font-size:13px"><br></div><div style="font-size:13px">I&#39;m a new member of the list, so apologies if this is a duplicate of an existing idea or if there&#39;s already a way to do this in Swift 2.1 that I&#39;ve missed.</div><div style="font-size:13px"><br></div><div style="font-size:13px">In Objective C, and C-like languages, an initialiser function represents a stage after allocation of memory where properties are given values. In Swift, init appears to precede (or overlap with) allocation. The benefit of this is that for type-safety reasons, all properties of a type (or new properties of a derived type) can be verified as having values. The disadvantage, and one of the stumbling blocks for those who learned Objective-C, is that until all the properties have values, the instance does not exist and instance functions cannot be called.</div><div style="font-size:13px"><br></div><div style="font-size:13px">There&#39;s an invisible threshold in Swift init() functions marking this transition. In derived classes it&#39;s the point where super.init() is called - after the derived type has provided initial values, but before any type functions can be called.</div><div style="font-size:13px"><br></div><div style="font-size:13px">Some types have multiple initialisers, and may be duplicating a lot of code in those distinct inits before they cross the threshold. This code can&#39;t be refactored into an instance function because the instance doesn&#39;t exist yet. The instance function may not even require the use of any properties of the type.</div><div style="font-size:13px"><br></div><div style="font-size:13px">If the compiler can read an init function and its varied control flow and determine a threshold where all properties have values, presumably it can read the code of any function called before that threshold, determine which properties they read and which they assign to, and provide a warning if a path assigns to a constant a second time, etc.. But this isn&#39;t currently happening.</div><div style="font-size:13px"><br></div><div style="font-size:13px">I&#39;m guessing there are multiple contributing factors for this: the combinatorial explosion of possible control flow paths with functions (particularly if they&#39;re recursive); the possibility that the function calls are used by the compiler to mark the end of a control flow path, by which point it can determine whether everything has a value; the function genuinely can&#39;t exist without allocation. I don&#39;t know the reasons but I&#39;d be interested to learn them.</div><div style="font-size:13px"><br></div><div style="font-size:13px">I&#39;m proposing the keyword &#39;selfless&#39; for a function which could be called before the threshold. It either only uses local properties or properties belonging to the type - never to the &#39;super&#39; type (in the case of a derived class). It can&#39;t call any instance functions which aren&#39;t themselves selfless.</div><div style="font-size:13px"><br></div><div style="font-size:13px">Example of use:</div><div style="font-size:13px">class FooView : UIView</div><div style="font-size:13px">{</div><div style="font-size:13px">    var property : Int</div><div style="font-size:13px"><br></div><div style="font-size:13px">    init()</div><div style="font-size:13px">    {</div><div style="font-size:13px">        initialiseProperty()</div><div style="font-size:13px">        super.init()</div><div style="font-size:13px">    }</div><div style="font-size:13px"><br></div><div style="font-size:13px">    init(frame:CGRect)</div><div style="font-size:13px">    {</div><div style="font-size:13px">        initialiseProperty()</div><div style="font-size:13px">        super.init(frame)</div><div style="font-size:13px">    }</div><div style="font-size:13px"><br></div><div style="font-size:13px">    selfless func initialiseProperty()</div><div style="font-size:13px">    {</div><div style="font-size:13px">        property = 4</div><div style="font-size:13px">    }</div><div style="font-size:13px">}</div><div style="font-size:13px"><br></div><div style="font-size:13px">Is this something of interest?</div><div style="font-size:13px"><br></div><div style="font-size:13px">Regards,</div><div style="font-size:13px">Ross O&#39;Brien</div></div>
</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=kND2tqgLiolwf1-2Bhgg7fFiaPS455NT9j3CATwJCX709M8hiwx2WKZSJCELkcBqGY-2Fm7C5QG8i1r7K0obNubBiUnShJis2gooF4fSIiXTBBMSr9UgX2ZROjIqp9RIgB89m43DWaP-2FcgQ-2FrZWu-2B6mJF5gC0gzYISEBCFYK-2FshlecsFTtDb0vQs-2FEc2sKG0am9nKzpi5IXOiEt-2B7ZJ2bHjK6frTL1VmI598aZojB9-2FCUBk-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">
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br><div>+1. This is something that I was planning to propose. It comes up particularly often in Cocoa objects that implement NSCoding, where you have to implement both init(coder:) and the designated initializer. Currently, if you have a bunch of complicated code involved in setting defaults for your properties, in a manner that’s too complex to solve with simple default values, you end up with a lot of copy-paste code in the two initializers, which can easily get out of sync if one is edited without being diligent about editing the other one in the same way. The exception, of course, if if you make init(coder:) a convenience initializer, but then subclasses cannot call super’s implementation of init(coder:), which makes this unworkable in a lot of circumstances.</div><div><br></div><div>I’m not sure “selfless” is the right keyword for this, but some sort of feature along these lines would be incredibly helpful.</div><div><br></div><div>Charles</div><div><br></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=6ZGE61OxINd5lLe2xYh9Ku-2BXbixWNr2nvfzp2IB1sZgZGqJhi5KiKFRGqvop-2FOKBH-2BYQAAWuUsgtyL8WZTBCFhDG3z7xExokHj-2FxmqIFLom-2FSZPWxSNWQ9dEWwTw1wniaszpTI7UZ7Ha2HvWABrq2SjKDJQ5jJvxq6A-2BEtDRZX55vSJG-2Fq8cVuZZ4sU4b9oYkO1v0DplNANhuY5vkDEQWQ-3D-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">
</div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
</div></div></blockquote></div><br></div>