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

Reply via email to