> On Jun 30, 2016, at 11:07 AM, Andrew Trick <[email protected]> wrote: >> On Jun 30, 2016, at 1:21 AM, John McCall via swift-evolution >> <[email protected]> wrote: >> >>> On Jun 29, 2016, at 10:17 PM, L. Mihalkovic <[email protected]> >>> wrote: >>>> On Jun 29, 2016, at 8:39 PM, Vladimir.S via swift-evolution >>>> <[email protected]> wrote: >>>> >>>> How about `public(extensible)` ? >>>> >>>> On 29.06.2016 21:32, John McCall via swift-evolution wrote: >>>>>> On Jun 29, 2016, at 11:16 AM, Michael Peternell via swift-evolution >>>>>> <[email protected]> wrote: >>>>>> Do you mean `public(unsealed)`? Because `internal(unsealed)` doesn't >>>>>> really make sense. `internal` declarations are always sealed. >>>>> >>>>> Right. >>>>> >>>>> If "sealed" is the default behavior for public classes and methods — and >>>>> I don't think the modifier is worth adding unless it's the default >>> >>> What a jump... I am very curious about this rational that seems so obvious >>> to you? >> >> There are a thousand different ways to add minor variations on language >> features. In almost every single thread of any length on this list, you can >> find someone who got attached to a slightly different feature from the one >> that eventually got picked, and often you can find them asking why we didn't >> just add that, too, maybe under a different name or using different syntax. >> If we added every single one of those, the language would not be better, it >> would just be absurdly, dauntingly complex. We have to look at these kinds >> of additive features with a very critical eye and decide how much code will >> really benefit from it. >> >> In our experience, idiomatic Swift libraries don't center that much around >> classes, and especially not around class inheritance. Value types are >> usually a better and more efficient data representation than juggling shared >> mutable state, and protocols are a cleaner and much more robust tool for >> polymorphism than overriding methods. Classes are useful for modeling >> values with "identity", but even then, the class itself can often be final: >> when its operations need to be polymorphic, it's usually better to just pass >> in a closure or an existential, because piling up overrides turns code into >> spaghetti very quickly. >> >> That doesn't mean we don't want to add good tools for classes, of course, >> but inheritance and overriding have a lot of subtle interactions, both at a >> low level with other language features and at a high level with any attempt >> to establish basic object invariants. Programmers want an endless variety >> of language tools for ensuring that overrides satisfy the contract correctly >> — "require the super method to be called", "require the super method to be >> called in exactly this way", "require the super method to be called unless >> the method exits early", "only allow calls to these specific other methods", >> "require this method to be called before doing anything else", ad infinitum. >> The only way we could possibly support all that is by first adding some >> massive new contracts feature and then embellishing it with a ton of >> inheritance-specific logic; in other words, everything with classes quickly >> balloons into a a huge research project, because (in my opinion) overriding >> is just an inherently clumsy tool. >> >> So when you look at something like 'sealed' as an opt-in modifier, you have >> to think carefully about who is actually going to use it. It's an explicit >> modifier that limits inheritance, but we already have 'final', so it's only >> useful when the library wants to provide its own private subclasses, but >> doesn't want to commit to full public inheritability. How often does that >> happen, really? Are we adding this feature for a handful of developers in >> the entire world, most of whom could probably find another solution to their >> problem? And that's for 'sealed' on a class — are we really supposed to >> expect that someone will unseal a class, but individually protect all the >> methods and properties they don't want overridden? >> >> In contrast, 'sealed' as a default is a conservative protection against >> forgetting to add 'final' (which will quickly get caught if the class is >> truly meant to be subclassed), and applied method-by-method it encourages >> the developer to think carefully about where they want the extension points >> to be on their class. Moreover, it enables a number of interesting language >> enhancements which can only be done safely with complete knowledge of the >> inheritance tree, and it significantly improves performance without adding >> any invasive annotations. And because it's already there as the default >> behavior, that handful of developers who actually need it specifically can >> get it for free. >> >> John. > > 100% agree. Sealed-by-default is the only thing that makes sense to me at > module boundaries and would obsolete the use of final-like keywords as > magical performance tools. I was dismayed to see “final” added out of > performance necessity and would love to see it return to a pure role as an > API constraint. > > To me, module is about what parts of the system can be compiled independently > and support binary distribution. That’s being conflated with source > distribution, but it should be possible to separate those concerns.
Agreed. Where we do have source distributions of modules, we should of course take advantage of the fact that we're compiling things together, but ultimately we want binary modules to be as efficient as possible. John. _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
