The point here is that the escape of the inner value necessitates the 
(implicit) escape of the outer captured value.  That's something closures don't 
have to deal with.

~Robert Widmann

2016/12/24 13:13、Callionica (Swift) <[email protected]> のメッセージ:

> I may be missing your point about lifetime extension problems. How would  
> lifetime extension be different for captures by classes than for captures by 
> function closures?
> 
>> On Sat, Dec 24, 2016 at 12:00 PM Robert Widmann <[email protected]> 
>> wrote:
>> 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 
>> <[email protected]> のメッセージ:
>> 
>>> Missed swift-evol in my reply
>>> 
>>> ---------- Forwarded message ---------
>>> From: Callionica (Swift) <[email protected]>
>>> 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 <[email protected]>
>>> 
>>> 
>>> 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 
>>>> <[email protected]> wrote:
>>>> 
>>> 
>>>> On Dec 23, 2016, at 1:10 AM, Callionica (Swift) via swift-evolution 
>>>> <[email protected]> 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 <[email protected]> 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) 
>>>> <[email protected]> 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 
>>>> <[email protected]> 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 
>>>> <[email protected]> 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 <[email protected]> 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 
>>>> >> <[email protected]> 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
>>>> 
>>>> 
>>>> >> [email protected]
>>>> 
>>>> 
>>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>>> 
>>>> >
>>>> 
>>>> 
>>>> _______________________________________________
>>>> 
>>>> 
>>>> swift-evolution mailing list
>>>> 
>>>> 
>>>> [email protected]
>>>> 
>>>> 
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> 
>>>> swift-evolution mailing list
>>>> 
>>>> [email protected]
>>>> 
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected]
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to