Sent from my iPad
> On Mar 2, 2017, at 9:06 PM, T.J. Usiyan <[email protected]> wrote: > > +1 overall. prefer this approach over the "scope based" approach in the other > proposal Can you elaborate? What problems are you hoping submodules will address? > >> On Wed, Feb 22, 2017 at 10:10 AM, Matthew Johnson via swift-evolution >> <[email protected]> wrote: >> >>>> On Feb 21, 2017, at 11:54 PM, Robert Widmann <[email protected]> >>>> wrote: >>>> >>>> >>>> On Feb 22, 2017, at 12:41 AM, Matthew Johnson <[email protected]> >>>> wrote: >>>> >>>> >>>> >>>> Sent from my iPad >>>> >>>>> On Feb 21, 2017, at 11:09 PM, Robert Widmann <[email protected]> >>>>> wrote: >>>>> >>>>> >>>>>>> On Feb 21, 2017, at 11:59 PM, Matthew Johnson <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>> >>>>>>> On Feb 21, 2017, at 10:41 PM, Robert Widmann <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>> By API boundaries I mean both the one internal to MyModule.Foo and the >>>>>>> one defined by MyModule. Here “the API boundary” is explicitly about >>>>>>> the submodule MyModule.Foo, whose internal state may have been >>>>>>> “unsealed” in the top level by the extension, but has not been >>>>>>> re-exported. >>>>>> >>>>>> I’m sorry, but I just don’t understand how modules form an API boundary >>>>>> in this system. To me a boundary means something that blocks access. >>>>>> In this system `internal` ranges over the entire module and all >>>>>> submodules. The only boundaries I can see besides the module itself are >>>>>> files and lexical scopes (with `fileprivate` and `private`). >>>>>> >>>>> >>>>> A module is a named region that introduces a lexical scope into which >>>>> declarations may be nested. The name of the module can be used to access >>>>> these member declarations. A module, like other aggregate structures in >>>>> Swift, may be extended with new declarations over one or more translation >>>>> units (files). >>>>> >>>>> >>>>> Your API boundary lives, as it does today, at the edges of each >>>>> (sub)module declaration. APIs that are public or open in a module >>>>> defines code that is free to move across this boundary and into the open. >>>>> APIs that are internal are free to have their modules unsealed into >>>>> other internal modules to enable modular composition. APIs that are >>>>> private and fileprivate do not participate in the API boundary because >>>>> they are not eligible for any kind of export. >>>>> >>>>> If any of that is unclear, please let me know. >>>> >>>> Yes, in fact parts are unclear. >>>> >>>> "APIs that are public or open in a module defines code that is free to >>>> move across this boundary and into the open" >>>> >>>> This is unclear because you're saying submodules form an API boundary and >>>> you're also saying we need to make APIs open or public to allow them to >>>> move across this boundary. But then you say we can unseal it (import or >>>> extend, right?) within the module and gain visibility to the internal >>>> symbols. Are you trying to say that it's a soft boundary within the >>>> module that can be permeated with an import or by extension? >>> >>> Of course. Soft implies more permeability than you are actually afforded, >>> but if you want to think of it that way then it may help to put it in >>> context. >>> >>> For what it’s worth, the bulk of the discussion around this feature is >>> focused on author-side concerns like the behavior of internal modules >>> because access control makes a mess of any reasonable semantics. >>> >>>> >>>> If so, that's not the kind of boundary I think many of us are talking >>>> about. We're talking about a hard boundary within the module, but broader >>>> than a file. >>> >>> How then, does one go about accessing declarations contained in these kinds >>> of impermeable modules? You must define points of exposure to be able to >>> use the module. What you’re describing is as though you had can only build >>> hierarchies of completely private types and then cherry-pick them >>> one-by-one into the open - which, mind you, is not a pattern encouraged by >>> any of the access control levels we have today and isn’t supported by any >>> language I’m aware of. >> >> There are ways to do this without requiring cherry picking individual types. >> I’m not looking for impermeable modules. I’m looking for bounded >> visibility within the module in a way that is very similar to `fileprivate`, >> but at a larger granularity. I’m writing up my view of submodules so we >> have something more concrete to discuss. >> >>> >>>> >>>>>> means that it is trivial to put code anywhere within the module that >>>>>> extends the submodule and wraps a symbol in a new name and declares it >>>>>> `public`. >>>>> >>>>> Precisely. That’s the same pattern that good Swift code, arguably good >>>>> code in any language that enables hiding, uses today. >>>>> >>>>>> They can also trivially add a `public import MyModule.Foo` anywhere at >>>>>> the top level of their file because every file is forced to include top >>>>>> level scope. >>>>> >>>>> Perhaps you misunderstand. Say the APIs in MyModule.Foo were all of >>>>> internal or stricter access: The re-export is a no-op. You cannot change >>>>> the access level of declarations, you can only do the modular thing and >>>>> wrap them in a palatable interface for export by a module you want to be >>>>> user-facing. You have to decide to make an API public, just as today you >>>>> have to decide to make part of an interface public. I don’t see how this >>>>> is distinct from the goals of this proposal. >>>> >>>> Yes, I understand this. But submodules aren't visible outside the module >>>> by default. It's possible for a submodule to have public and open symbols >>>> without the top level public import anywhere in the program. >>> >>>> What I'm saying here is that someone in a distant part of the code base >>>> could arbitrarily add it if they decided to. The system doesn't prevent >>>> it. >>>> >>> >>> Because, by definition, you are not in a “distant part of the codebase” >>> when you are extending a module. You’re introducing related functionality >>> under the same namespace with more related functionality. Anything else is >>> fundamentally anti-modular because it pollutes different concerns together >>> into an interlocking directorate. Miles away implies cognitive and >>> semantic distance when you’re probably physically in the same directory! >>> >>>> I understand that you consider that a non goal. I'm simply pointing out >>>> that the system has this property. I think it's reasonable to want a >>>> system with different properties. And I don't think it's clear yet >>>> exactly what kind of system might garner the support necessary to be >>>> accepted as Swift's submodule system. That's part of the reason we have >>>> these discussions! :) >>> >>> I so appreciate this, too. I genuinely enjoy discussions that try to poke >>> holes and prod out better explanations. It’s how you iterate on proposals >>> and just make good things happen in a community like this. >>> >>> ~Robert Widmann >>> >>>> >>>>> >>>>>> >>>>>> In my opinion, we need to identify what goals we have for a submodule >>>>>> system - what problems are we trying to solve and what use cases do we >>>>>> intend to enable. >>>>>> >>>>>> There are quite a few of us who want the ability to form solid API >>>>>> boundaries inside a module and view this as one of the fundamental >>>>>> features of a submodule system. It’s reasonable to ask why we view this >>>>>> capability as essential. >>>>>> >>>>>> I can’t speak for anyone else, but here are a few reasons why it’s >>>>>> important to me: >>>>>> >>>>>> * Solid API boundaries are essential to good design. >>>>>> * Having access to an entire code base does not reduce the benefits of >>>>>> #1. Some code bases are substantial in size and hard boundaries are >>>>>> important to keeping them manageable. >>>>>> * Using full-fledged modules to do this is possible, but also involves a >>>>>> bit of ceremony that is incidental, not essential complexity in many >>>>>> cases. It would be better to have a lighter weight mechanism to do this. >>>>>> * Swift currently only has whole module optimization, not whole program >>>>>> optimization. There is a performance penalty to using full-fledged >>>>>> modules. >>>>>> >>>>>>> >>>>>>> ~Robert Widmann >>>>>>> >>>>>>>>> On Feb 21, 2017, at 11:38 PM, Matthew Johnson >>>>>>>>> <[email protected]> wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> On Feb 21, 2017, at 10:29 PM, Robert Widmann >>>>>>>>> <[email protected]> wrote: >>>>>>>>> >>>>>>>>> This level of access, the “private to this submodule except to the >>>>>>>>> select set of interfaces I want to see it” level, is the equivalent >>>>>>>>> of friend classes in C++. I don’t consider leaving this out to be a >>>>>>>>> hole, nor is it an "encapsulation-related problem” because at no >>>>>>>>> point can you break the API boundary and re-export anything here with >>>>>>>>> a higher level of access than it had previously. >>>>>>>> >>>>>>>> By API boundary you mean the top-level module, right? >>>>>>>> >>>>>>>>> >>>>>>>>>>> On Feb 21, 2017, at 11:13 PM, Matthew Johnson >>>>>>>>>>> <[email protected]> wrote: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> On Feb 21, 2017, at 10:11 PM, Matthew Johnson >>>>>>>>>>>> <[email protected]> wrote: >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>>> On Feb 21, 2017, at 9:47 PM, Brent Royal-Gordon via >>>>>>>>>>>>> swift-evolution <[email protected]> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> On Feb 21, 2017, at 7:38 PM, Robert Widmann >>>>>>>>>>>>> <[email protected]> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> Correct. Because, in dividing the submodule across an extension, >>>>>>>>>>>>> you have placed what should be a private API into a >>>>>>>>>>>>> differently-scoped location. >>>>>>>>>>>> >>>>>>>>>>>> Okay. So is your submodule design not intended to address the "I >>>>>>>>>>>> want to encapsulate implementation details so they're only visible >>>>>>>>>>>> to several units of code in different files, but not the entire >>>>>>>>>>>> module" use case? Because if there's no way to scope a symbol to >>>>>>>>>>>> "everything inside this submodule, but nothing outside this >>>>>>>>>>>> submodule", I think it leaves that use case unserved. >>>>>>>>>>> >>>>>>>>>>> Unless I’m missing something there is also another >>>>>>>>>>> encapsulation-related problem with the proposed design. Let’s >>>>>>>>>>> suppose for the sake of discussion there was a `submoduleprivate` >>>>>>>>>>> access modifier (intentionally ungainly and not realistic). >>>>>>>>>>> >>>>>>>>>>> // File 1 >>>>>>>>>>> module Foo { >>>>>>>>>>> // internal, visible to the whole module >>>>>>>>>>> class Bar { submoduleprivate var protectedState: Int = 0 } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> // File 2 - Has nothing to do with Foo at all >>>>>>>>>>> import MyModule.Foo >>>>>>>>>>> >>>>>>>>>>> module NotFoo { >>>>>>>>>>> // Hey, I need to see Bar.protectedState!!! >>>>>>>>>>> func totallyNotFoo() { >>>>>>>>>>> var bar = Bar() >>>>>>>>>>> bar.foosExposedPrivates = 42 >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> // ok, I’ll just add an extension to Foo so I can see >>>>>>>>>>> submoduleprivate and wrap what I need >>>>>>>>>>> module Foo { >>>>>>>>>> >>>>>>>>>> Oops, this should have been `extension Foo`, but otherwise I believe >>>>>>>>>> it is valid under this proposal. >>>>>>>>>> >>>>>>>>>>> // Hey, I’ll be nice and keep it fileprivate, but I could make it >>>>>>>>>>> public if I wanted to. >>>>>>>>>>> extension Foo { >>>>>>>>>>> fileprivate var foosExposedPrivates: Int { >>>>>>>>>>> // Yep, I’m inside Foo so I can see it’s submoduleprivate >>>>>>>>>>> stuff >>>>>>>>>>> get { return protectedState } >>>>>>>>>>> set { protectedState = newValue } >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Brent Royal-Gordon >>>>>>>>>>>> Architechies >>>>>>>>>>>> >>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>> 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
