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