<div dir="ltr">On Sat, Jan 14, 2017 at 9:36 AM, Joseph Newton <span dir="ltr">&lt;<a href="mailto:jnewto32@gmail.com" target="_blank">jnewto32@gmail.com</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr">Thank you for your responses Xiaodi and David,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="gmail-"><span style="background-color:rgba(255,255,255,0)">I believe you can do this using didSet without the `_bar`:<br></span></span><span class="gmail-"><span style="background-color:rgba(255,255,255,0)">class Foo {<br></span><span class="gmail-m_-3380429028517004120gmail-im"><span style="background-color:rgba(255,255,255,0)">    public var bar: String? {</span></span><span style="background-color:rgba(255,255,255,0)">       </span> </span></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="background-color:rgba(255,255,255,0)">        didSet {<br></span><span class="gmail-"><span style="background-color:rgba(255,255,255,0)">            if (bar?.characters.count ?? 0) &lt; 100 {<br></span><span style="background-color:rgba(255,255,255,0)">                bar = nil<br></span><span style="background-color:rgba(255,255,255,0)">            }<br></span><span style="background-color:rgba(255,255,255,0)">        }<br></span><span style="background-color:rgba(255,255,255,0)">    }<br></span><span style="background-color:rgba(255,255,255,0)">}</span></span></blockquote><div><br></div><div>Yes, although this is a perfectly valid way of implementing this, I&#39;m not a big fan of implementing this functionality in this way. Particularly, I don&#39;t like the concept of validating data after setting it, and then re-setting the property if the validation failed. I would much rather implement it in a manner where it&#39;s conditionally set depending on validation.</div><span class="gmail-"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.800000190734863px">It&#39;s an interesting idea, for sure. Because of the persistent storage required for `_bar`, I </span><i style="font-size:12.800000190734863px">think</i><span style="font-size:12.800000190734863px"> one way to look at what you&#39;re proposing is </span><span style="font-size:12.800000190734863px;background-color:rgba(255,255,255,0)">essentially as </span><span style="font-size:12.800000190734863px">a way to allow for a variable to be declared publicly as one type, be implemented as another (anonymous, in this case) type under the hood, and to specify a mechanism for automatically converting between the two types.</span></blockquote><div><br></div></span><div>Essentially, yes. The programmer would have the option of using these nested properties to be able to add custom storage or functionality to any computed property that they please.</div><span class="gmail-"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.800000190734863px">(That said, there is a recurrent theme on this list where people ask for new support for encapsulating members from visibility in ever smaller scopes. I continue to be not in favor of the new `private`, but even allowing its existence, providing all the permutations of type/file/extension visibility is (afaict) and should continue to be (imo) a non-goal. The distinction between public and internal not only avoids pollution in your autocomplete list but also provides important safety wins, and I think those gains are increasingly limited the finer we dice these access levels.)</span></blockquote><div><br></div></span><div>I&#39;m not sure that I quite understand what you mean by this. Would you mind elaborating? </div></div></div></blockquote><div><br></div><div>See below.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><span class="gmail-"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <span style="font-size:12.800000190734863px">I get that your proposal allows you to write one fewer declaration in the case of an ad-hoc behavior than SE-0030 would. That is, in the case of SE-0030, you&#39;d have to declare both a behavior and a member that uses it; in your case, you could declare just the member and implement the behavior there. However, I think I&#39;d want to see some concrete use cases that are better served by this proposal than by SE-0030, which is the more general solution as far as I can tell. In the two use cases you&#39;ve mentioned, one is served by `didSet`, and the other (`synchronized`) is a reusable behavior for which SE-0030 offers the more elegant solution.</span></blockquote><div><br></div></span><div>Here are some additional uses cases for this proposal:</div><div><br></div><div><b>Implementing Objective-C&#39;s &quot;__null_resettable&quot;</b></div><div><br></div><div>class Foo {</div><div>    var bar: UIColor! {</div><div>        var _bar: UIColor = .clear</div><div>        </div><div>        get { _return _bar }</div><div>        set { _bar = newValue ?? .clear }</div><div>    }</div><div>} </div></div></div></blockquote><div><br></div><div>In this use case, your proposal differs from what&#39;s currently possible only in that `_bar` (presumably, after you write `private` in front of it, for consistency with current rules about default access levels) would be invisible even inside `Foo`. As I wrote to you above, avoiding &quot;pollution&quot; within ever smaller scopes [in this case, the scope inside `Foo`] is (AFAICT) and should be (IMO) a non-goal. To convince me that this use case is worth the engineering effort and complexity of a new syntax, you&#39;d also have to convince me that having `_bar` visible within the entire scope of `Foo` has practical and not merely theoretical footgun potential or some other negative impact beyond the fact that autocomplete will show a member you&#39;d rather not see.</div><div><br></div><div>_Even if_ I were to buy that argument, I think there is a more general solution that covers your use case. A few months earlier on this list, several people discussed the possibility of same-module extensions allowing stored properties, to very positive reception. There are numerous use cases for that feature, but such a feature would also allow you to isolate `_bar` and `bar` in its own extension, a common Swift idiom. It would also allow you to group this implementation in the same extension with arbitrary functions that need to see `_bar` (such as your `init(_:)` example below) without exposing `_bar` to other initializer and methods that don&#39;t need to manipulate it. This would be both more flexible and more fine-grained than possible with your own proposal, and if I were to buy your argument that `_bar` being visible where it&#39;s not needed is suboptimal, this would be the optimal solution.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><b>Implementing a stack interface</b></div><div><b><br></b></div><div>class Foo&lt;T&gt; {</div><div>    var currentItem: T? {</div><div>        var storage = [T]()</div><div><br></div><div>        get { return storage.last }</div><div>        set {</div><div>            if let newValue = newValue {<br></div><div>                storage.append(newValue)<br></div><div>            }<br></div><div>            else {<br></div><div>                storage.removeLast()<br></div><div>            }<br></div><div>        }</div><div>    }</div><div>}</div></div></div></blockquote><div><br></div><div>I&#39;m not sure I understand why this requires your proposed feature, other than again that it hides `storage` from the rest of `Foo&lt;T&gt;`.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><b>Validation before changing (for performance)</b></div><div><b><br></b></div><div>class SessionManager {</div><div>    var session: Session {</div><div>        var _session: Session</div><div><br></div><div>        get { return _session }</div><div>        set {</div><div>            if newValue != _session {</div><div>            // expensive teardown code for the old session<br></div><div><br></div><div>            _session = newValue</div><div><br></div><div>            // expensive setup code for the new session <br></div><div>            }</div><div>        }</div><div>    }</div><div>}</div></div></div></blockquote><div><br></div><div>This can be implemented using `willSet` and `didSet` (taking your example at face value, where it&#39;s not the actual swapping of newValue and _session that is expensive but rather the teardown and setup, assuming `==` and `!=` are implemented correctly, i.e. in such a way that `newValue == _session` implies that the two fully instantiated values really are interchangeable in every way that matters).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div>Lastly, I&#39;ve been doing some additional thinking and I think that it would be beneficial to also setting values for these nested properties inside of <i>init</i> methods. For example, I work with C APIs a great deal and create Swift/ObjC wrappers for them a lot, I have a case where I provide an implementation as follows:</div><div><br></div><div>class Wrapper {</div><div>    private var _unmanaged: UnsafePointer&lt;UInt8&gt;</div><div>    var text: String {</div><div>        return String(cString: _unmanaged)</div><div>    }</div><div><br></div><div>    fileprivate init(_ unmanaged: UnsafePointer&lt;UInt8&gt;) {</div><div>        _unamanged = unmanaged</div><div>    }</div><div>}</div><div><br></div><div>It&#39;s implemented in this manner because the C APIs may change the characters pointed to by <i>_unmanaged</i> before the <i>text</i> property is accessed. With this proposal, this code could be implemented as follows:</div><div><br></div><div><div>class Wrapper {</div><div>    var text: String {</div><div>        private var unmanaged: UnsafePointer&lt;UInt8&gt;</div><div><br></div><div>        get {</div><div>            return String(cString: unmanaged)</div><div>        }</div><div>    }</div><div><br></div><div>    fileprivate init(_ unmanaged: UnsafePointer&lt;UInt8&gt;) {</div><div>        self.text.unmanaged = unmanaged</div><div>    }</div><div>}</div></div></div></div></blockquote><div><br></div><div>Unless I&#39;m mistaken, this addendum to your idea can&#39;t be reconciled with access control rules. A `private` var is hidden from _all_ methods not in scope. One shouldn&#39;t (and probably can&#39;t, from an implementation perspective) start making rules saying that certain `private` vars are visible to initializers.</div><div><br></div><div>Using your proposed feature, you&#39;d have to make `unmanaged` in this case `fileprivate` and then implement the rest of `Wrapper` in an extension in a different file if you want to hide `unmanaged` from those methods but leave it visible to your initializer. By contrast, if you left `unmanaged` as a private var directly inside `Wrapper`, you could hide `unmanaged` from any methods implemented in an extension without having to move that extension to a different file, probably a cleaner result if this kind of fine-grained hiding from autocomplete is what you&#39;re after.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail-h5"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jan 13, 2017 at 4:01 PM, Xiaodi Wu <span dir="ltr">&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>(Forward to the list if your early replied was intended to be sent there.)</div><span><div><br></div><div><br></div>On Fri, Jan 13, 2017 at 1:58 PM, Joseph Newton <span dir="ltr">&lt;<a href="mailto:jnewto32@gmail.com" target="_blank">jnewto32@gmail.com</a>&gt;</span> wrote:<br></span><div class="gmail_extra"><div class="gmail_quote"><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I believe that you&#39;re referring to <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md" target="_blank">SE-0030 Property Behaviors</a>, correct?<br><br></div><div>I have indeed read over this proposal (I probably should have mentioned that in my first message) but I don&#39;t believe that it quite covers what I&#39;m going for (or over-covers it).</div></div></blockquote><div><br></div></span><div>The reason I mentioned it was because the use case sounded vaguely familiar. Reading over SE-0030, you&#39;ll see that one specific example is synchronized property access. It demonstrates how SE-0030 would enable a behavior called `synchronized` that would allow you to write, for any arbitrary member foo, `public [synchronized] var foo: String`. It would make it more than just easy to implement such a behavior for any member: you would not have to write anything but `[synchronized]`.</div><div><br></div><div>As to your other use case, the case of validating a set value, David Sweeris has pointed out that `didSet` currently enables that functionality pretty well.</div><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>SE-0030 proposes making property behaviors requiring a specific declaration and implementation of a particular behavior just to be able to add stored properties to computed properties. Additionally, if you look at the &quot;Properties and Methods in Behaviors&quot; section of the proposal, you&#39;ll see that any stored property declared inside of a behavior is given the same access level as the property that is using the behavior. Although this could be convenient in some circumstances, my proposal calls for these stored properties to be private to the scope of the property declaration so as to avoid namespace pollution.<br></div></div></blockquote><div><br></div></span><div>I think you misunderstand that text, or maybe I do. It says that the properties and methods are expanded into the containing scope, and that they must be of _types_ that are visible at the call site. However, the examples given for reimplementing lazy show very clearly that the properties and methods can be declared private:</div><div><br></div><div>```</div><div><div>public var behavior lazy&lt;Value&gt;: Value {</div><div>  private var value: Value?</div></div><div>  // ...</div><div>}</div><div>```</div><div><br></div><div>SE-0030 was written before `fileprivate` and `private` were separated; if it were implemented today, it would make sense that `private` would cause `value` to be invisible outside the behavior. Even at the time, a `private` underlying `value` shouldn&#39;t be (unless I&#39;m mistaken) visible outside the file.</div><div><br></div><div>(That said, there is a recurrent theme on this list where people ask for new support for encapsulating members from visibility in ever smaller scopes. I continue to be not in favor of the new `private`, but even allowing its existence, providing all the permutations of type/file/extension visibility is (afaict) and should continue to be (imo) a non-goal. The distinction between public and internal not only avoids pollution in your autocomplete list but also provides important safety wins, and I think those gains are increasingly limited the finer we dice these access levels.)</div><span><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>My proposal makes this feature (stored properties inside of computed properties) significantly easier to implement. For singular or unique cases of needing this functionality, in lieu of having to learn &quot;Property Behaviors,&quot; its syntax and how to effectively write them, one would only need to add their properties to their computed properties&#39; declaration block.<br><br></div><div>Thoughts?</div></div></blockquote><div><br></div></span><div>I get that your proposal allows you to write one fewer declaration in the case of an ad-hoc behavior than SE-0030 would. That is, in the case of SE-0030, you&#39;d have to declare both a behavior and a member that uses it; in your case, you could declare just the member and implement the behavior there. However, I think I&#39;d want to see some concrete use cases that are better served by this proposal than by SE-0030, which is the more general solution as far as I can tell. In the two use cases you&#39;ve mentioned, one is served by `didSet`, and the other (`synchronized`) is a reusable behavior for which SE-0030 offers the more elegant solution.</div><div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769h5"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-HOEnZb"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-h5"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jan 13, 2017 at 12:34 PM, Xiaodi Wu <span dir="ltr">&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">There was a proposal for custom behaviors using `@`, which if I recall would offer encapsulation along the lines of what you&#39;re proposing. It was an extensively designed system which was deferred for consideration, but which would be in scope again in phase 2. The proposal is in the swift-evolution repository--does that address your use case?<br><div class="gmail_quote"><div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775h5"><div dir="ltr">On Fri, Jan 13, 2017 at 11:27 Joseph Newton via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br></div></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775h5"><div dir="ltr" class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">Hi,<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>I&#39;ve done a lot of Objective-C and have been been a fan of Swift since it&#39;s come out, however, there&#39;s a small feature of Objective-C that I would really like to see implemented in Swift:<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>In Objective-C you have a few options implementation-wise when creating properties for your class. You could use the <i class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">@synthesize </i>statement to have the compiler create the backing ivar along with the appropriate accessor methods<i class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"> </i>or your could use the <i class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">@dynamic</i> statement to tell the compiler that you&#39;re going to create your own accessor methods and backing ivar (if needed).<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>Additionally, one could use the <i class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">@synthesize</i> statement to have the compiler create the backing ivar, and then they could create custom accessor methods to supply custom functionality or validation. I use this third case extensively in my Objecitve-C code but there&#39;s not a concise way of doing this in Swift.<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>For example, I might have an Objective-C implementation that looks like this:<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>@interface Foo : NSObject<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">@property (nullable, copy) NSString *bar;<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>@end<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>@implementation Foo<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">@synthesize bar = _bar; // Creates ivar &#39;_bar&#39;<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">- (void)setBar:(NSString *)bar {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    if (bar.length &lt; 100)<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        _bar = nil;<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    else<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        _bar = [bar copy];<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">}<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>@end<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>Currently, the only way to implement this in Swift - AFAIK - is as follows:<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>class Foo {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>    private var _bar: String?<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>    public var bar: String? {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>        get { return _bar }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>        set {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>            if (newValue?.characters.count ?? 0) &lt; 100 {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>                _bar = nil<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            else {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">                _bar = newValue.copy() as! String<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">}<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">Although this works, it isn&#39;t exactly glamorous. The main drawback of this implementation (unless intended) is that you now have any additional &#39;_bar&#39; variable accessible within the scope of your class. <br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">My proposal is to allow stored properties in the declaration block of computed properties. For this example, the &#39;_bar&#39; declaration would simply be moved inside of the declaration block for &#39;bar&#39;:<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">class Foo {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    public var bar: String? {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        var _bar: String?<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        get { return _bar }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        set {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            if (newValue?.characters.count ?? 0) &lt; 100 {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">                _bar = nil<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            else {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">                _bar = newValue.copy() as! String<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">            }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div>        }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">}<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">Only the getter and setter methods of &#39;bar&#39; are allowed to access and modify the stored &#39;_bar&#39; property. My proposal would also allow for multiple stored properties of varying types within the scope of a single computed property. This would also simply atomic synchronization for single variables:<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">class Foo {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    static var synchronizedBar: String? {<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        var queue = DispatchQueue(label: &quot;Foo.synchronizedBar&quot;)<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        var bar: String?<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        get { return queue.sync { return bar } }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">        set { queue.sync { bar = newValue } }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">    }<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">}<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">Are there any suggestions or arguments, for or against, for this proposal?<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div><div class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">-- Joe Newton<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg"></div></div></div></div></div></div></div></div></div></div>
______________________________<wbr>_________________<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">
swift-evolution mailing list<br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br class="gmail-m_-3380429028517004120gmail-m_2172644783927788769m_-3519070023270271731gmail-m_-6875955485106384775m_1111025934970820808gmail_msg">
</blockquote></div>
</blockquote></div><br></div>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div></div></div></div>
</blockquote></div><br></div></div>