[swift-evolution] [Review] SE-0018 Flexible Memberwise Initialization

Matthew Johnson matthew at anandabits.com
Fri Jan 8 13:19:31 CST 2016


> On Jan 8, 2016, at 1:17 PM, Kevin Ballard <kevin at sb.org> wrote:
> 
> On Fri, Jan 8, 2016, at 11:15 AM, Matthew Johnson wrote:
>> 
>>> On Jan 8, 2016, at 1:05 PM, Kevin Ballard via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> I had another thought last night about this proposal. Since it appears to be working as syntactic sugar, if I write something like
>>> 
>>> var x: Int
>>> memberwise init(...) {
>>>   // what does x refer to here?
>>> }
>>> 
>>> Inside of the memberwise init, does the bare identifier `x` refer to the property, or to the implicit parameter? I think it should refer to the property, because making it refer to the implicit parameter means you'd be referring to a variable that was never visibly declared anywhere.
>>> AFAIK the only precedent for that is the implicit argument `newValue` to setters, `oldValue` to didSet observers, and `error` to catch blocks, but those are all constant identifiers that mean the same thing in every such context, as opposed to memberwise init where the implicit parameters are different for each init. More generally, we should avoid exposing such non-declared variables without a compelling reason.
>>> 
>>> The other argument in favor of making `x` refer to the property is because that's just generally more useful. All the properties match the values of the parameters on the first line of the user-supplied body to the memberwise init, so there's no benefit to be had from leaving the parameters accessible to user code.
>>> 
>>> As for how to actually accomplish this, assuming this feature is implemented as an AST transformation, ideally we'd have some way to synthesize identifiers in the AST that cannot possibly be referenced by user code (e.g. some form of identifier namespacing if it exists, or some form of gensym-like behavior). Alternatively, if there's no particularly good way to do this, we could just use something like `__name` as the internal parameter name.
>> 
>> Thanks for bringing this up Kevin.  I agree it should refer to the property.  Not sure what, but for some reason I didn’t think to state this explicitly in the proposal.  In fact, my examples accidentally implied otherwise because they didn’t show the compiler using a mangled name of some kind for the internal parameter name in the expansions.
>> 
>> The only downside is that it changes behavior if you transition from a memberwsie initializer to a manual initializer.
> 
> If you transition to a manual initializer you can provide your own mangled internal parameter names for your manual initializer, so there's no behavioral change. And in most cases the distinction won't actually matter anyway, it's just the cases where a property may change during initialization (either due to modifying it directly, or due to calling a method that modifies it and then reading the property afterwards) where you actually care that the identifier refers to the property.

Yes, of course.  But if you forget to provide your own internal name it would be a behavior change.  I agree in most cases it wouldn’t matter much either way.  I just thought it was important to point out that there is a rare case where it could result in something unintended / unexpected.

Matthew

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160108/ad12fd78/attachment.html>


More information about the swift-evolution mailing list