That still doesn't answer the lifetime extension problems. What is being described here is a complex extension to the lifetime of memory that is only being kept alive because of these implicit captures. It sounds like what you want is a member, and I'm not sure it's worth saving 5 lines to avoid that fact.
~Robert Widmann 2016/12/24 11:45、Callionica (Swift) via swift-evolution <swift-evolution@swift.org> のメッセージ: > Missed swift-evol in my reply > > ---------- Forwarded message --------- > From: Callionica (Swift) <swift-callion...@callionica.com> > Date: Sat, Dec 24, 2016 at 9:44 AM > Subject: Re: [swift-evolution] Should we relax restriction on closing over > outer scope in class declarations? > To: Robert Widmann <devteam.cod...@gmail.com> > > > These are good questions. > > I believe Swift closures currently do implicit self-capture. I wouldn't > expect that behavior to be different when capturing for classes. > > If a class needs to refer to an outer self, I would expect the user to have > to give the outer self a new name by assigning to a local. Same deal for > referring to members in an outer class where there are members of the same > name in the inner class: assign outer self to a local and refer to members > through that local. > >> On Fri, Dec 23, 2016 at 10:16 AM, Robert Widmann <devteam.cod...@gmail.com> >> wrote: >> > >> On Dec 23, 2016, at 1:10 AM, Callionica (Swift) via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> I'm certainly assuming that users have a basic understanding of scope >> (without that, what would be the intention behind defining the class within >> the function?). > > Despite its simplicity to you (given the example you’ve cited) this feature > is quite an advanced extension to the current scoping rules. > >> I'm not clear on what you see as the downside of letting classes capture >> locals for users that are unaware of capturing. > > I’ll be blunt: This opens a gaping hole in the semantics of variable > lifetimes and potentially introduces an ambiguity into resolution of the > `self` keyword. For the former, consider a light extension to your original > example that introduces a nested class: > > class Outer { > let widgetString: String = createWidgetString() > > // Initializer suppressed > func foo() -> WidgetStringProvider { > class SimpleProvider: WidgetStringProvider { > // Initializer suppressed > func provideWidgetString() -> String { > return widgetString > } > } > return SimpleProvider() > } > } > > Now, from SIL’s point of view, widgetString must escape the scope it’s in > and its lifetime should be extended beyond this block. Fine. But what about > Outer? Because we’re returning a reference to SimpleProvider which escapes > the scope of foo(), and instance members of a SimpleProvider capture outer > context, this means we also have to keep Outer alive and around for > destruction (perhaps at the point where SimpleProvider is destroyed?) > > For the latter consider trying to explicitly reference widgetString here. > In provideWidgetString() we close over self in both foo() and > provideWidgetString(). So, if I wish to make reference to Outer’s self > explicitly, how would I go about doing it? Given that today a nested > aggregate can have members with the same identifiers as their parent, how do > we know if we’re capturing them or not when they’re referenced in the inner > aggregate? > > ~Robert Widmann > >> On Thu, Dec 22, 2016 at 11:26 PM Xiaodi Wu <xiaodi...@gmail.com> wrote: >> Only if you're also assuming that people defining classes within functions >> would know about capturing. This violates the principle of progressive >> disclosure, since people naturally learn about functions and classes before >> they learn about closures and capturing. >> >> >> On Fri, Dec 23, 2016 at 01:51 Callionica (Swift) >> <swift-callion...@callionica.com> wrote: >> Assuming capture were allowed, people defining classes within functions who >> didn't want them to capture could position the class definition prior to any >> other code in the function so that there would be nothing to capture. >> >> On Thu, Dec 22, 2016 at 4:13 PM Xiaodi Wu via swift-evolution >> <swift-evolution@swift.org> wrote: >> I have to agree with Michael; it seems dangerous to allow implicit capture >> by classes. A primary purpose (telos?) of closures is to provide this >> functionality, which is actually quite an advanced concept. One knows to >> think carefully about this when encountering a closure expression. A primary >> purpose of classes is to provide for encapsulation of code. Accidentally >> extending the lifetime of a local variable in a containing scope would be >> hard to notice and highly unexpected functionality. Better not to mix these >> things. >> >> On Thu, Dec 22, 2016 at 17:54 Micah Hainline via swift-evolution >> <swift-evolution@swift.org> wrote: >> That's exactly what I'm suggesting, the class declaration could work >> similarly to a closure. >> >> >> >> >> >> > On Dec 22, 2016, at 4:15 PM, Michael Ilseman <milse...@apple.com> wrote: >> >> >> > >> >> >> > Are you asking for a class declaration to implicitly capture and extend >> > the lifetime of local variables? That seems like something that’s better >> > done explicitly. Perhaps it’s better to think about how to reduce the >> > boiler plate code, e.g. better default initializers. >> >> >> > >> >> >> > (this is of course, additive and beyond the current scope of Swift 4 phase >> > 1 planning) >> >> >> > >> >> >> >> On Dec 22, 2016, at 2:39 PM, Micah Hainline via swift-evolution >> >> <swift-evolution@swift.org> wrote: >> >> >> >> >> >> >> >> Currently we allow declarations of a new class in local scope, but >> >> >> >> nothing can be referenced from the outer scope. Thus this is illegal: >> >> >> >> >> >> >> >> ``` >> >> >> >> func foo() { >> >> >> >> let widgetString: String = createWidgetString() >> >> >> >> class SimpleProvider: WidgetStringProvider { >> >> >> >> func provideWidgetString() -> String { >> >> >> >> return widgetString // Illegal, defined in outer scope >> >> >> >> } >> >> >> >> } >> >> >> >> doThingsWithWidget(provider: WidgetStringProvider()) >> >> >> >> } >> >> >> >> ``` >> >> >> >> >> >> >> >> I'm trying to feel out the edges of this decision, and figure out why >> >> >> >> exactly this isn't allowed now, and how we might want to relax this in >> >> >> >> the future if possible. While not a common construct, it is a useful >> >> >> >> one. >> >> >> >> >> >> >> >> Obviously there are ways around it, very simple to create an init and >> >> >> >> a private let and do something like this: >> >> >> >> >> >> >> >> ``` >> >> >> >> func foo() { >> >> >> >> let widgetString: String = createWidgetString() >> >> >> >> class SimpleProvider: WidgetStringProvider { >> >> >> >> private let widgetString: String >> >> >> >> >> >> >> >> init(widgetString: String) { >> >> >> >> self.widgetString = widgetString >> >> >> >> } >> >> >> >> >> >> >> >> func provideWidgetString() -> String { >> >> >> >> return widgetString // now legal, references >> >> >> >> SimpleProvider.widgetString >> >> >> >> } >> >> >> >> } >> >> >> >> doThingsWithWidget(provider: WidgetStringProvider(widgetString: >> >> >> >> widgetString)) >> >> >> >> } >> >> >> >> ``` >> >> >> >> >> >> >> >> That's boilerplate I don't want to write though, as it somewhat >> >> >> >> detracts from the readability of the structure. I'm not super >> >> >> >> interested in defending the concept of local class definitions itself, >> >> >> >> it's already allowed in the language, I'm just interested in the >> >> >> >> syntax limitation and where that line might be able to be redrawn. >> >> >> >> _______________________________________________ >> >> >> >> swift-evolution mailing list >> >> >> >> swift-evolution@swift.org >> >> >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> > >> >> >> _______________________________________________ >> >> >> swift-evolution mailing list >> >> >> swift-evolution@swift.org >> >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >> >> _______________________________________________ >> >> swift-evolution mailing list >> >> swift-evolution@swift.org >> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> >> >> >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > > > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution