-
Re: Mutually Recursive Protocols / Compiler Crash
Dave Aug 22, 2015 11:45 AM (in response to GoZoner)Don't know if there's a syntactically valid way to do it, but does it work if source and target are weak or unowned?
Edit: I thought maybe the compiler was trying to save you from a reference cycle, but I tried it with both weak and unowned, and no difference. Splitting <Person> into two protocols compiles, though.
protocol Person : Hashable { var fullname : String { get set } } protocol PersonInRelationship : Person { typealias R : Relationship var relationships : Array<R> { get } } protocol Relationship : Hashable { typealias P : Person var source : P { get } var target : P { get } }
-
Re: Mutually Recursive Protocols / Compiler Crash
OOPer Aug 22, 2015 4:20 PM (in response to GoZoner)Compiler should not crash and I don't know if this case matches any of the known issues. You should send a Bug Report.
Is the above a coding-style that is to be avoided (in a language like Swift)?
I'm afraid the answer for this question is Yes.
When Swift applies a protocol as a type constraint, it needs to infer the actual types of the associated types.
So, when you use Person protocol, Person.R needs to be inferred.
And, any arbitrary type conforming to Relationship can be Person.R, Swift needs to infer Person.R.P,
two types conforming to Person and Person.R.P may be different, so this makes an inifinite recursion, not mutual recursion:
Person.R.P, Person.R.P.R, Person.R.P.R.P, ...
You may already know, if you remove Hashable, you can write something like this:
protocol Relationship { var source : Person { get } var target : Person { get } } protocol Person { var fullname : String { get set } var relationships: [Relationship] {get} }
If you want to make all actual implementation of Person and Relationship to be Hashable, you can make derived protocols and use them:
protocol PersonType: Person, Hashable {} protocol RelationshipType: Relationship, Hashable {}
One more, you should consider if both type may be value types, when you define mutually dependent types.
-
Re: Mutually Recursive Protocols / Compiler Crash
GoZoner Aug 28, 2015 10:07 AM (in response to OOPer)I asked specifically about 'coding style' because there is something about my modelling style that causes me to hit these issues _every_ time.
If I don't expose `var Relationship : Set<Relationship>` and instead add methods like `addFriend`, `mapFriends`, `mapRivals`, etc (all the different facets of a Relationship - or addRelationship:as:) then the problem is avoided - Relationship becomes an implementation detail of Person. That is workable; maybe I learn something about modeling from that.
Regarding the 'infinite recursion', is there not something like a `where` clause on a `typealias`?
protocol Person : Hashable { var fullname : String { get set } typealias R : Relationship where R.P == Self var relationships : Set<R> { get } }
-
Re: Mutually Recursive Protocols / Compiler Crash
OOPer Aug 28, 2015 12:50 PM (in response to GoZoner)Having `where` constraint in `typealias` of protocols seems to be a possible extension for me, you'd better write a feature request.
I'm not sure the feature make this case easier, but it can be a good tool to represent our idea more straightforward.
And maybe we need some more good tools to use Swift as a really Protocol Oriented Programming language.
-
-
-
Re: Mutually Recursive Protocols / Compiler Crash
GoZoner Aug 28, 2015 12:07 PM (in response to GoZoner)No longer crashes in: Apple Swift version 2.0 (700.0.57 700.0.72). Issues a warning of 'Type may not reference itself as a requirement'.
-
Re: Mutually Recursive Protocols / Compiler Crash
davidlondono Jan 7, 2016 8:10 AM (in response to GoZoner)there is a warning but not a solution
I want to use it for VIPER, and the type alias conclict is on the View, Presenter and Interactor
protocol ViewControllerProtocol: class { typealias PresenterType:PresenterProtocol var presenter:PresenterType! {get set} } protocol PresenterProtocol: class { typealias InteractorType: InteractorProtocol typealias ViewControllerType: ViewControllerProtocol weak var view: ViewControllerType! {get set} var interactor: InteractorType! {get set} init() } protocol InteractorProtocol:class { typealias PresenterType: PresenterProtocol weak var presenter:PresenterType! {get set} init() }
i get the "Type may not reference itself as a requirement" error so dont know how to do it
if I erase the typealias type doesent work to use the Routing as generic and ad a func
presenter.interactor = newInteract loginPresenter.routing = self loginPresenter.view = viewController
-