> 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] 
> <mailto:[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] <mailto:[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] <mailto:[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] <mailto:[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] 
> > <mailto:[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] <mailto:[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] <mailto:[email protected]>
> 
> 
> >> https://lists.swift.org/mailman/listinfo/swift-evolution 
> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> >
> 
> 
> _______________________________________________
> 
> 
> swift-evolution mailing list
> 
> 
> [email protected] <mailto:[email protected]>
> 
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> 
> 
> _______________________________________________
> 
> swift-evolution mailing list
> 
> [email protected] <mailto:[email protected]>
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <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