On Wed, 27 Apr 2016, Антон Жилин wrote:

Yes, this is my proposal, and of course, I'm interested :)

Cool, given it's postponed until Swift 4+ I thought it best to keep this 
off-list but happy to keep going here if others don't find it distracting.

I've drafted a proposal focusing on the strict definition of Traits.  I'll give 
it another few iterations so I can flesh out where they could fit in the 
language relative to extensions etc.  Happy to share it here, or keep it 
off-list for now until we can dive into Swift's internals and come up with some 
ideas on how best to implement this.

I haven't read into the mentioned papers, but symmetric sum, asymmetric sum, 
alias, exclusion
and derived operations form a solid basis for conflict resolution.

Let's keep it very simple to begin with.  e.g. 3 Traits each implement one or 
more functions:

          function1    function2    function3    function4
TraitA       X             X           X
TraitB       X                                       X
TraitC                     X

for each column where there are >1 implementations, the conflict must be resolved 
explicitly by choosing which implementation will be used.  This is roughly how flattening 
works.  We "flatten" them into 1 cohesive set of methods, with no conflicts, e.g. 
consumption syntax could look ~like

        class Foo : ProtocolA {
                flattens TraitA, TraitB, TraitC { exclude TraitA.function1 
TraitC.function2 }
        }

or they could be re-used to provide protocol default implementations:

        protocol ProtocolA {
                flattens TraitA, TraitB, TraitC { exclude TraitB.function1 
TraitA.function2 }
        }

that also helps to resolve the dilemma of having to conform to a full protocol 
when you only use a couple of specific default implementations - you pick and 
choose from the underlying implementations, and/or conform to a more 
fine-grained sub-protocol.  I think Traits can help make extensions, protocols 
and default implementations more powerful, concise and re-usable.  They seem to 
complement each other well.

Note that the Trait doesn't target a named Class or Protocol like extensions 
do, the onus is reversed so that the consuming 
class/struct/enumeration/protocol elects to consume that implementation(s).  
This means they are more fine-grained and re-usable than default 
implementations, and in reality I think default implementations could be 
provided by a protocol *or* a Trait, or both (say the Class conforms to the 
Protocol, but chooses to override a default implementation with an alternative 
from a Trait).

Renaming functions, aliasing, keeping all implementations available for the 
final function to call ... I'd leave all of this complexity until later.

State as well, that should remain a class/struct/enumeration responsibility.  Stateful 
Traits could be attempted later, Trait functions could benefit from some shared state 
amongst themselves, but that state should not be visible outside of that 
"instance" of Trait - the same Trait consumed elsewhere would have its own 
state, and no consumer could access this state.  This also means that there are no Type 
size issues as we're not introducing additional stored properties.

I believe there are situations where non-privateness of fields would help, see 
my two examples.
This can be overridden by adding a "proxy" computed property. But why is 
privateness needed?

Do traits have initializers? How do they work in diamond pattern?

Example: A -> (B, C) -> D
B.init calls A.super.init(1)
C.init calls A.super.init(2)
D.init calls B.super.init() and C.super.init()

Traits are flattened by default. Does it mean that A will be initialized twice? 
in what state
will A be?

Traits cannot be instantiated, they are not inherited, and they do not have 
state.  So multiple inheritance and the diamond problem are not applicable 
here.  Swift's existing rules around single-inheritance remain as-is.

Computed properties I can see a valid argument for supporting, but not stored 
properties.  Initialisation is the responsibility of the 
class/struct/enumeration, not the Trait.  Traits are not a solution to this 
problem.

The white paper is a really good read, highly recommend it: 
http://scg.unibe.ch/archive/papers/Scha02bTraits.pdf

--
Niall Young
[email protected]

2016-04-27 2:50 GMT+03:00 Niall Young <[email protected]>:
      On Fri, 22 Apr 2016, Антон Жилин wrote:

            This feature has been previously discussed. Search for Mixins on
            swift-evolution archives.

            I believe it would help to read previous version of the proposal:
            
https://github.com/Anton3/swift-evolution/blob/mixins/proposals/NNNN-mixins.md


      Cheers, already read through the thread - I'm more focused on 
implementing Traits,
      which I think is very similar but slightly different to what's been 
described in the
      thread to date.

      Is this your proposal?  I'd love to give you some feedback, throw ideas 
back and
      forth if you're interested?  If we can evolve the concept and 
implementation by
      Swift 4 that gives me enough time to brush up on C++ and start delving 
into Swift
      internals to see how best it could be done.

      Cheers,

      --
      Niall Young
      [email protected]
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to