Neat. Seems like that'd be a bug.
On Wed, Apr 19, 2017 at 9:40 PM, Howard Lovatt <[email protected]> wrote: > As it stands at the moment splitting to multiple files doesn't work. EG: > > ModuleA > > A.swift > > public protocol P { > > func m() -> String > > } > > extension Int: P { > > public func m() -> String { > > return "AP.m" > > } > > } > > ModuleB > > B.swift > > public protocol P { > > func m() -> String > > } > extension Int: P { > > public func m() -> String { > > return "BP.m" > > } > > } > > ModuleC > > A.swift > > import ModuleA > > > func am(_ i: Int) -> String { return i.m() } > > B.swift > > import ModuleB > > > func bm(_ i: Int) -> String { return i.m() } > > main.swift > > let i = 0 > > print(am(i)) > print(bm(i)) > > > Gives the following errors when built: > > sunzero-ln:ModuleC lov080$ swift build > Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleA > Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleB > Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleA > Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleA at 1.0.0 > Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleB > Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleB at 1.0.0 > Compile Swift Module 'ModuleB' (1 sources) > Compile Swift Module 'ModuleA' (1 sources) > Compile Swift Module 'ModuleC' (3 sources) > /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleC/Sources/B.swift:3:38: error: ambiguous use of 'm()' > func bm(_ i: Int) -> String { return i.m() } > ^ > ModuleA.Int:2:17: note: found this candidate > public func m() -> String > ^ > ModuleB.Int:2:17: note: found this candidate > public func m() -> String > ^ > /Users/lov080/Google Drive/Swift/Examples/Example Module > Clashes/ModuleC/Sources/A.swift:3:38: error: ambiguous use of 'm()' > func am(_ i: Int) -> String { return i.m() } > ^ > ModuleA.Int:2:17: note: found this candidate > public func m() -> String > ^ > ModuleB.Int:2:17: note: found this candidate > public func m() -> String > ^ > <unknown>:0: error: build had 1 command failures > error: exit(1): /Applications/Xcode.app/Contents/Developer/Toolchains/ > XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f > /Users/lov080/Google\ Drive/Swift/Examples/Example\ Module\ > Clashes/ModuleC/.build/debug.yaml > > As you can see that despite each file A and B in ModuleC only importing > one module each all the extensions apply even if not explicitly imported. > > -- Howard. > > On 18 April 2017 at 11:47, Xiaodi Wu <[email protected]> wrote: > >> Simple: you put the user code that needs the more accurate library in one >> file and import only the more accurate library there, and you put the user >> code that needs the more performant library in a separate file and import >> only the more performant library there! Swift's devotion to file-based >> organization presents endless avenues of flexibility! >> >> What you write is an argument for designing a more expressive import >> and/or disambiguation feature, not for disallowing public retroactive >> conformance. A proposal to rip out entirely the ability to vend public APIs >> with extensions is simply not going to fly. The core team has committed to >> a small standard library and multiple independent core libraries like >> Foundation. This can only work because Foundation can greatly expand the >> API of standard library types through extensions. >> >> Your proposal would undo that design decision and require folding >> Foundation's functionality into the standard library, or rewriting the >> entire Foundation overlay to encapsulate standard library types instead of >> extending them. For example, NSString would have to be a separate type that >> encapsulates String. Yet oodles of work have gone into making NSString >> seamlessly bridge to String in the first place. >> On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <[email protected]> >> wrote: >> >>> Comments in-line below >>> >>> -- Howard. >>> >>> On 17 Apr 2017, at 9:01 am, Xiaodi Wu <[email protected]> wrote: >>> >>> This continues to forbid use cases that are critical. >>> >>> >>> I think "critical" is overstating the importance. Plenty of successful >>> languages do not have extensions. Extensions have been discussed and >>> rejected by successful languages. The .NET guidelines suggest considered >>> cautious use. I have tried to encapsulate the best practice into a language >>> feature. >>> >>> >>> For instance, I am writing a library that vends additional conformances >>> for Float and Double. Any numerics library would need to do the same. >>> >>> >>> You need to consider this carefully because your numerics library might >>> add a method sinh for example and the user of your library might be using >>> other numerical libraries as well, one of these others might also provide >>> sinh. Which is to be called in the user code by f.sinh? Suppose one library >>> emphasises speed over accuracy and the other vice versa. You really want >>> access to both versions in the user code. This is a situation I have come >>> across a few times in numeric C, Java, and C++ with matrix libraries where >>> code I have worked on has used multiple libraries in the same application >>> for good reason. >>> >>> I think you would be better vending functions for things like sinh, >>> rather than extending float with an additional function, and vending types >>> for more complex things like matrices, rather than extending arrays with >>> dot products for example. If you vend a type you can easily give access to >>> the underlying type using composition rather than extension or inheritance, >>> there is an example of this in the proposal just above the Justification >>> section.. >>> >>> >>> Your design would eliminate all such libraries, which is a non-starter. >>> I am not sure what defects you are trying to solve with this proposal. >>> >>> I am trying to make Swift more consistent, easier to learn, and to >>> encourage third-party libraries. >>> >>> >>> On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <[email protected]> >>> wrote: >>> >>>> @Brent, >>>> >>>> I have updated the proposal to address your concerns, in particular I >>>> don't see that retrospectively adding methods and protocols has been >>>> removed it has just had its ugly corners rounded. See revised proposal >>>> below particularly the end of section "Retrospectively adding >>>> protocols and methods" and new section "Justification". >>>> >>>> Hope this convinces you that the change is worthwhile. >>>> >>>> -- Howard. >>>> >>>> ==================================== >>>> >>>> # Proposal: Split extension usage up into implementing methods and >>>> adding methods and protocols retrospectively >>>> >>>> >>>> ## Revision history >>>> >>>> | Version | Date | Comment | >>>> >>>> |---------|--------------|--------------| >>>> >>>> | Draft 1 | 11 April 2017 | Initial version | >>>> >>>> | Draft 2 | 13 April 2017 | Added support for post-hoc conformance to >>>> a protocol - replaced static final extensions with final extensions | >>>> >>>> | Draft 3 | 17 April 2017 | Added justification section | >>>> >>>> >>>> ## Introduction >>>> >>>> >>>> Currently extension methods are confusing because they have different >>>> dispatch rules for the same calling syntax. EG: >>>> >>>> >>>> public protocol P { >>>> >>>> func mP() -> String >>>> >>>> } >>>> >>>> extension P { >>>> >>>> func mP() -> String { return "P.mP" } >>>> >>>> func mE() -> String { return "P.mE" } >>>> >>>> } >>>> >>>> struct S: P { >>>> >>>> func mP() -> String { return "S.mP" } >>>> >>>> func mE() -> String { return "S.mE" } >>>> >>>> } >>>> >>>> let s = S() >>>> >>>> s.mP() // S.mP as expected >>>> >>>> s.mE() // S.mE as expected >>>> >>>> let p: P = s // Note: s now typed as P >>>> >>>> p.mP() // S.mP as expected >>>> >>>> p.mE() // P.mE unexpected! >>>> >>>> >>>> Extension methods can also cause compatibility problems between >>>> modules, consider: >>>> >>>> >>>> In Module A >>>> >>>> extension Int: P { >>>> >>>> func m() -> String { print("A.m") } >>>> >>>> } >>>> >>>> >>>> In Module B >>>> >>>> extension Int: P { >>>> >>>> func m() -> String { print("B.m") } >>>> >>>> } >>>> >>>> >>>> In Module C >>>> >>>> import A >>>> >>>> import B // Should this be an error >>>> >>>> let i = 0 >>>> >>>> i.m() // Should it return A.m or B.m? >>>> >>>> >>>> This proposal cures the above two problems by separating extension >>>> methods into two seperate use cases: implementations for methods and adding >>>> methods and protocols retrospectively. >>>> >>>> >>>> ## Implementing methods >>>> >>>> >>>> If the extension is in the same file as the protocol/struct/enum/class >>>> declaration then it implements the methods and is dispatched using a >>>> Vtable. EG: >>>> >>>> >>>> File P.swift >>>> >>>> protocol/struct/enum/class P { >>>> >>>> // func m() not declared in type since it is added by the >>>> extension, under this proposal it is an error to include a declaration in a >>>> type *and* in an extension >>>> >>>> } >>>> >>>> extension P { >>>> >>>> func m() { print("P.m") } // m is added to the >>>> protocol/struct/enum/class declaration >>>> >>>> } >>>> >>>> >>>> Same or other file >>>> >>>> struct S: P { >>>> >>>> override func m() { print("S.m") } // Note override required >>>> because m already has an implementation from the extension >>>> >>>> } >>>> >>>> let p: P = S() // Note typed as P >>>> >>>> p.m() // Now prints S.m as expected >>>> >>>> >>>> Extensions in the same file as the declaration can have any access, can >>>> be final, and can have where clauses and provide inheritable >>>> implementations. >>>> >>>> >>>> In a protocol at present there is a difference in behaviour between a >>>> protocol that declares a method that is then implemented in an extension >>>> and a protocol that just has the method implemented in an extension and no >>>> declaration. This situation only applies to protocols, for >>>> structs/enumerated/classes you cannot declare in type and implement in >>>> extensions. The proposal unifies the behaviour of >>>> protocol/struct/enum/class with extensions and prevents the error of a >>>> minor typo between the protocol and extension adding two methods instead of >>>> generating an error. >>>> >>>> >>>> The implementation needed to achieve this proposal is that a value >>>> instance typed as a protocol is copied onto the heap, a pointer to its >>>> Vtable added, and it is passed as a pointer. IE it becomes a class >>>> instance. No change needed for a class instance typed as a protocol. >>>> >>>> >>>> ## Retrospectively adding protocols and methods >>>> >>>> >>>> A new type of extension is proposed, a "final extension", which can be >>>> either in or outside the file in which the protocol/struct/enum/class >>>> declaration is in. EG: >>>> >>>> >>>> protocol P2 { >>>> >>>> func m2P() >>>> >>>> } >>>> >>>> final extension S: P2 { // Note extension marked final >>>> >>>> func m2P() { print("SP2.m2P") } // Implicitly final, completely >>>> implements P2 >>>> >>>> func m2E() { print("SP2.m2E") } // Implicitly final, not an >>>> existing method >>>> >>>> } >>>> >>>> >>>> Which are called as any other method would be called: >>>> >>>> >>>> let s = S() >>>> >>>> s.m2P() // Prints SP2.m2P >>>> >>>> s.m2E() // Prints SP2.m2E >>>> >>>> >>>> A method added by a final extension is is implicitly final, as the name >>>> would suggest, and cannot be overridden. >>>> >>>> >>>> Notes: >>>> >>>> >>>> 1. If the final extension adds a method, e.g. m2E, that method cannot >>>> already exist. IE a final extension cannot override an existing method or >>>> implement a protocol declared method that lacks an implementation unless it >>>> also adds the protocol. >>>> >>>> >>>> 2. If the final extension adds a protocol then it must implement all >>>> the methods in that protocol that are not currently implemented. >>>> >>>> >>>> 3. If the final extension is outside of the file in which the >>>> protocol/struct/enum/class declaration is in then the extension and the >>>> methods can only have fileprivate or internal access. This prevents >>>> retrospective extensions from numerous modules clashing, since they are not >>>> exported outside of the module. >>>> >>>> >>>> When a type is extended inside a module with a final extension the >>>> extension is not exported. For example: >>>> >>>> >>>> final extension Int: P2 { >>>> >>>> func m2P() { print("Int.m2P") } >>>> >>>> } >>>> >>>> >>>> If an exported function uses Int, e.g.: >>>> >>>> >>>> public func f(_ x: Int) -> Int { >>>> >>>> x.m2P() >>>> >>>> return x >>>> >>>> } >>>> >>>> >>>> Then when used in an external module both the input Int and the output >>>> Int are not extended with P2. However as the Int goes into f it gains P2 >>>> conformance and when it leaves it looses P2 conformance. Thus inside and >>>> outside the module the behaviour is easily understood and consistent and >>>> doesn't clash with other final extensions in other modules. >>>> >>>> >>>> Taking the above example further an Int with P2 conformance is required >>>> by the user of a library; then it can simply and safely be provided, e.g.: >>>> >>>> >>>> public class P2Int: P2 { >>>> >>>> var value = 0 >>>> >>>> func m2P() { print("Int.m2P") } >>>> >>>> } >>>> >>>> >>>> This type, P2Int, is easy to write, one line longer than a final >>>> extension, and can easily be used as both a P2 and an Int and does not >>>> clash with another Int extension from another module. >>>> >>>> >>>> ## Justification >>>> >>>> >>>> The aim of Swift is nothing more than dominating the world. Using the >>>> current, April 2017, https://www.tiobe.com/tiobe-index/ index of job >>>> adverts for programmers the languages that are in demand are: Java 15.568%, >>>> C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic >>>> .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, >>>> Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a >>>> new language and is already above Objective-C at 14th. However there is >>>> obviously a long way to go and the purpose of this proposal is to help with >>>> this climb. >>>> >>>> >>>> A characteristic of many of the languages above Swift in the Tiobe >>>> Index is that they have major third party libraries; for some languages >>>> they are almost defined by their third part libraries, e.g. Ruby for Rails. >>>> A major part of this proposal is to make extensions safe when using >>>> multiple libraries from different venders. In particular final extensions >>>> are not exported. >>>> >>>> >>>> As part of Swift's goal of world domination is that it is meant to be >>>> easy to learn by a process of "successive disclosure". The current >>>> inconsistent behaviour of protocols and extensions hinders this process and >>>> is a common gotcha for newbies. This proposal eliminates that problem also. >>>> >>>> >>>> Extensions are not new in languages, they are part of the .NET >>>> languages for example. Since .NET popularised extensions they have been >>>> discussed by other language communities, particularly Java and Scala, and >>>> in the academic community (normally termed the Expression Problem) however >>>> they have not proved popular because of the problems they cause. Nearly all >>>> languages have a strong bias towards keeping the language small and simple >>>> and trade of the advantages of a feature against the disadvantages and the >>>> feature only makes it into the language if it offers many advantages, has >>>> few disadvantages, and is not heavily overlapping with other features. This >>>> keeping it small and simple test is what extensions have failed in other >>>> languages. >>>> >>>> >>>> Experience from .NET can however be used to improve extensions. There >>>> is some excellent advice https://blogs.msdn.microsoft.c >>>> om/vbteam/2007/03/10/extension-methods-best-practices- >>>> extension-methods-part-6/ written by the VB .NET team when they added >>>> extensions to VB .NET. The best-practice advice can be summarised by the >>>> following quotes from the reference: >>>> >>>> >>>> 0. "In most real world applications these suggestions [the rest of >>>> the suggestions] can (and quite frankly should!) be completely ignored." >>>> This is an important observations, in your own code that is not intended >>>> for reuse; go for it, use extensions. The proposal importantly still allows >>>> this style of programming and in fact improves it by adding consistent >>>> behaviour and syntax between protocols/structs/enumerated/classes. >>>> >>>> >>>> 1. "Read the .NET Framework Class Library Design Guidelines." The >>>> equivalent for Swift is lacking at this stage. Probably because third party >>>> libraries are rare. >>>> >>>> >>>> 2. "Be wary of extension methods." This recommendation is formalised >>>> in the proposal by limiting final extensions to be fileprivate or internal. >>>> >>>> >>>> 3. "Put extension methods into their own namespace." This >>>> recommendation is formalised in the proposal by limiting final extensions >>>> to be fileprivate or internal. >>>> >>>> >>>> 4. "Think twice before extending types you don’t own." >>>> >>>> >>>> 5. "Prefer interface extensions over class extensions." Translation >>>> to Swift terminology provide default implementations for protocol methods. >>>> The proposal encourages this by eliminating a major gotcha with the current >>>> implementation, namely the proposal always dispatches via a Vtable to give >>>> consistent behaviour. >>>> >>>> >>>> 6. "Be as specific with the types you extend as possible." >>>> Translation to Swift terminology provide default implementations for >>>> protocol methods that extend other protocols if there is a more specific >>>> behaviour that is relevent. The proposal encourages this by eliminating a >>>> major gotcha with the current implementation, namely the proposal always >>>> dispatches via a Vtable to give consistent behaviour. >>>> >>>> >>>> The proposal formalises these best practices from .NET whilst >>>> increasing consistence and without loosing the ability to use extensions >>>> heavily in your own one-off code to allow for rapid development. Most of >>>> the best practices are for better libraries, particularly third party, >>>> which is an important area for future Swift growth onto the server side. >>>> This proposal actively encourages this transition to large formal server >>>> side code without loosing the free wheeling nature of app code. >>>> >>>> >>>> ## Possible future work (not part of this proposal) >>>> >>>> >>>> This proposal will naturally allow bodies to be added to protocols >>>> directly rather than via an extension, since under the proposal the >>>> extension adds the declaration to the type so it is a small step to allow >>>> the protocol methods to have an implementation. >>>> >>>> >>>> In an opposite sense to the above adding bodies to protocols, >>>> extensions could be allowed to add method declarations without bodies to >>>> protocols. >>>> >>>> >>>> The two above future work proposals, if both added, would add symmetry >>>> to where declarations and bodies may appear for protocols. >>>> >>>> >>>> ## In summary. >>>> >>>> >>>> The proposal formalises the split use of extensions into their two >>>> uses: implementing methods and post-hoc adding protocols and methods. >>>> Syntax is added that clarifies the two use cases, the former are termed >>>> extensions and must be in the same file as the type is declared, and the >>>> latter are termed final extensions and can be in any file, however if they >>>> are not in the type's file the they can only have fileprivate or internal >>>> access. >>>> >>>> >>>> Note the distinction between an extension in the same file and in a >>>> separate file is consistent with the philosophy that there is special >>>> status to the same file as proposed for private in >>>> https://github.com/apple/swift-evolution/blob/master/proposa >>>> ls/0169-improve-interaction-between-private-declarations- >>>> and-extensions.md. >>>> >>>> >>>> =================================================== >>>> >>>> >>>> #Proposal: Split extension usage up into implementing methods and >>>> adding methods and protocols post-hoc >>>> >>>> >>>> Draft 2 (Added support for post-hoc conformance to a protocol - >>>> replaced static final extensions with final extensions) >>>> >>>> >>>> ## Introduction >>>> >>>> >>>> Currently extension methods are confusing because they have different >>>> dispatch rules for the same calling syntax. EG: >>>> >>>> >>>> public protocol P { >>>> >>>> func mP() -> String >>>> >>>> } >>>> >>>> extension P { >>>> >>>> func mP() -> String { return "P.mP" } >>>> >>>> func mE() -> String { return "P.mE" } >>>> >>>> } >>>> >>>> struct S: P { >>>> >>>> func mP() -> String { return "S.mP" } >>>> >>>> func mE() -> String { return "S.mE" } >>>> >>>> } >>>> >>>> let s = S() >>>> >>>> s.mP() // S.mP as expected >>>> >>>> s.mE() // S.mE as expected >>>> >>>> let p: P = s // Note: s now typed as P >>>> >>>> p.mP() // S.mP as expected >>>> >>>> p.mE() // P.mE unexpected! >>>> >>>> >>>> Extension methods can also cause compatibility problems between >>>> modules, consider: >>>> >>>> >>>> In Module A >>>> >>>> extension Int: P { >>>> >>>> func m() -> String { print("A.m") } >>>> >>>> } >>>> >>>> >>>> In Module B >>>> >>>> extension Int: P { >>>> >>>> func m() -> String { print("B.m") } >>>> >>>> } >>>> >>>> >>>> In Module C >>>> >>>> import A >>>> >>>> import B // Should this be an error >>>> >>>> let i = 0 >>>> >>>> i.m() // Should it return A.m or B.m? >>>> >>>> >>>> This proposal cures the above two problems by separating extension >>>> methods into two seperate use cases: implementations for methods and adding >>>> methods and protocols post-hoc. >>>> >>>> >>>> ## Implementing methods >>>> >>>> >>>> If the extension is in the same file as the protocol/struct/class >>>> declaration then it implements the methods and is dispatched using a >>>> Vtable. EG: >>>> >>>> >>>> File P.swift >>>> >>>> protocol/struct/class P { >>>> >>>> // func m() not declared in type since it is added by the >>>> extension, under this proposal it is an error to include a declaration in a >>>> type *and* in an extension >>>> >>>> } >>>> >>>> extension P { >>>> >>>> func m() { print("P.m") } // m is added to the >>>> protocol/struct/class declaration >>>> >>>> } >>>> >>>> >>>> Same or other file >>>> >>>> struct S: P { >>>> >>>> override func m() { print("S.m") } // Note override required >>>> because m already has an implementation from the extension >>>> >>>> } >>>> >>>> let p: P = S() // Note typed as P >>>> >>>> p.m() // Now prints S.m as expected >>>> >>>> >>>> Extensions in the same file as the declaration can have any access, can >>>> be final, and can have where clauses and provide inheritable >>>> implementations. >>>> >>>> >>>> In a protocol at present there is a difference in behaviour between a >>>> protocol that declares a method that is then implemented in an extension >>>> and a protocol that just has the method implemented in an extension and no >>>> declaration. This situation only applies to protocols, for structs and >>>> classes you cannot declare in type and implement in extensions. The >>>> proposal unifies the behaviour of protocol/struct/class with extensions and >>>> prevents the error of a minor typo between the protocol and extension >>>> adding two methods instead of generating an error. >>>> >>>> >>>> The implementation needed to achieve this is that a value instance >>>> typed as a protocol is copied onto the heap, a pointer to its Vtable added, >>>> and it is passed as a pointer. IE it becomes a class instance. No change >>>> needed for a class instance typed as a protocol. >>>> >>>> >>>> ## Post-hoc adding protocols and methods >>>> >>>> >>>> A new type of extension is proposed, a "final extension", which can be >>>> either in or outside the file in which the protocol/struct/class >>>> declaration is in. EG: >>>> >>>> >>>> protocol P2 { >>>> >>>> func m2P() >>>> >>>> } >>>> >>>> final extension S: P2 { // Note extension marked final >>>> >>>> func m2P() { print("SP2.m2P") } // Implicitly final, completely >>>> implements P2 >>>> >>>> func m2E() { print("SP2.m2E") } // Implicitly final, not an >>>> existing method >>>> >>>> } >>>> >>>> >>>> Which are called as any other method would be called: >>>> >>>> >>>> let s = S() >>>> >>>> s.m2P() // Prints SP2.m2P >>>> >>>> s.m2E() // Prints SP2.m2E >>>> >>>> >>>> A method added by a final extension is is implicitly final, as the name >>>> would suggest, and cannot be overridden. >>>> >>>> >>>> If the final extension: >>>> >>>> >>>> 1. Adds a method, e.g. m2E, that method cannot already exist. IE a >>>> final extension cannot override an existing method or implement a protocol >>>> declared method that lacks an implementation unless it also post-hoc adds >>>> the protocol. >>>> >>>> >>>> 2. Adds a protocol then it must implement all the methods in that >>>> protocol that are not currently implemented. >>>> >>>> >>>> 3. Is outside of the file in which the protocol/struct/class >>>> declaration is in then the extension and the methods can only have >>>> fileprivate or internal access. This prevents post-hoc extensions from >>>> numerous modules clashing, since they are not exported outside of the >>>> module. >>>> >>>> >>>> ## Possible future work (not part of this proposal) >>>> >>>> >>>> This proposal will naturally allow bodies to be added to protocols >>>> directly rather than via an extension, since under the proposal the >>>> extension adds the declaration to the type so it is a small step to allow >>>> the protocol methods to have an implementation. >>>> >>>> >>>> In an opposite sense to the above adding bodies to protocols, >>>> extensions could be allowed to add method declarations without bodies to >>>> protocols. >>>> >>>> >>>> The two above future work proposals, if both added, would add symmetry >>>> to where declarations and bodies may appear for protocols. >>>> >>>> >>>> ## In summary. >>>> >>>> >>>> The proposal formalises the split use of extensions into their two >>>> uses: implementing methods and post-hoc adding protocols and methods. >>>> Syntax is added that clarifies the two use cases, the former are termed >>>> extensions and must be in the same file as the type is declared, and the >>>> latter are termed final extensions and can be in any file, however if they >>>> are not in the type's file the they can only have fileprivate or internal >>>> access. >>>> >>>> >>>> Note the distinction between an extension in the same file and in a >>>> separate file is consistent with the philosophy that there is special >>>> status to the same file as proposed for private in >>>> https://github.com/apple/swift-evolution/blob/master/proposa >>>> ls/0169-improve-interaction-between-private-declarations- >>>> and-extensions.md. >>>> >>>> >>>> ==================================== >>>> >>>> On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <[email protected]> >>>> wrote: >>>> >>>> On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>> [email protected]> wrote: >>>> >>>> >>>> I don't see that retroactive conformance needs to be exportable. If it >>>> is exported then you cannot prevent clashes from two modules, this is a >>>> known problem in C#. Because of this and other problems with C# extensions, >>>> this style of extension were rejected by other language communities >>>> (notably Java and Scala). >>>> >>>> >>>> A better alternative for export is a new class that encapsulates the >>>> standard type but with added methods for the protocol to be added. This way >>>> there is no clash between modules. EG: >>>> >>>> >>>> public protocol P { >>>> >>>> func m() -> String >>>> >>>> } >>>> >>>> public class PInt: P { >>>> >>>> var value = 0 >>>> >>>> func m() -> String { return "PI.m" } >>>> >>>> } >>>> >>>> >>>> Howard, this would be very source-breaking and would fail to achieve >>>> fundamental goals of Swift's protocol design. Removing retroactive >>>> conformance is no more realistic than removing Objective-C bridging—another >>>> feature which introduces various ugly edge cases and tricky behaviors but >>>> is also non-negotiable. >>>> >>>> -- >>>> Brent Royal-Gordon >>>> Architechies >>>> >>>> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
