> This means that the ChildGuardianship enum is no longer a real value type > with value semantics but a value type with partial reference semantics.
That's already true of any enum that has an associated reference type. > On May 6, 2016, at 10:26 AM, Michael Peternell <[email protected]> > wrote: > > >> Am 06.05.2016 um 14:08 schrieb Marc Prud'hommeaux <[email protected]>: >> >> >>> I wonder if there is a practical use-case for this.. Is there? Just >>> curious... >> >> Without getting too deep into the weeds of our specific data modal, I'll >> summarize with "yes". If you need to mix classes with enums and don't have >> the ability to declare the storage class of the variables, then reference >> cycles can only be avoided by shimming in some other type that does permit >> the declaration of the storage type. I would be surprised if I was the only >> person to encounter this issue; anyone else? >> >> It is analogous to the hoops you would need to jump through to define a >> recursive enum before the "indirect" keyword. As a matter of fact, it is so >> similar to that case that I wonder if it would make sense to have >> weak/unowned keywords be before the case name, as with indirect. E.g.: >> >> enum ChildGuardianship { >> unowned case ChildOf(Parent) >> indirect case GrandChildOf(ChildGuardianship) >> weak case WardOf(State?) >> } > > sorry, that doesn't really convince me. I don't consider a > "ChildGuardianship" enum a practical use-case. The same for "child", > "parent", "daughterOf", "sonOf", etc. Or were you programming a kindergarten > application to help the kindergarten teachers to bill the parents correctly? > > The obvious problem with a storage class in value types is that weak > references are by definition mutable: they zero out as soon as the pointee > starts deallocating. This means that the ChildGuardianship enum is no longer > a real value type with value semantics but a value type with partial > reference semantics. > > I'm sure there is a practical use-case for this somewhere, but I doubt that > it would be generally useful enough to be included into Swift at the language > level. > > -Michael > >> >> The obvious limitation of this would be that all associated types would be >> pegged to the same storage class, preventing the ability of having one >> associated type be weak and another be unowned. This limitation of indirect >> was mentioned at >> https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151207/000312.html >> , but it doesn't seem to have been given much treatment since. >> >> -Marc >> >> >>> On May 4, 2016, at 12:25 PM, Michael Peternell <[email protected]> >>> wrote: >>> >>> I wonder if there is a practical use-case for this.. Is there? Just >>> curious... >>> >>> -Michael >>> >>>> Am 03.05.2016 um 17:07 schrieb Marc Prud'hommeaux via swift-evolution >>>> <[email protected]>: >>>> >>>> >>>> The following code currently has a retain cycle and memory leak: >>>> >>>> enum ParentChild { >>>> case SonOf(Parent) >>>> case DaughterOf(Parent) >>>> } >>>> >>>> class Parent { >>>> lazy var son: Child = Child(parentChild: .SonOf(self)) >>>> lazy var daughter: Child = Child(parentChild: .DaughterOf(self)) >>>> deinit { print("deinit Parent") } >>>> } >>>> >>>> class Child { >>>> var parentChild: ParentChild >>>> init(parentChild: ParentChild) { >>>> self.parentChild = parentChild >>>> } >>>> deinit { print("deinit Child") } >>>> } >>>> >>>> >>>> do { >>>> let parent = Parent() >>>> parent.son >>>> parent.daughter >>>> } >>>> >>>> >>>> Child.parentChild cannot be declared unowned because ParentChild is a >>>> value type. I propose adding the ability to declare the reference storage >>>> class for an enum's associated value, like so: >>>> >>>> enum ParentChild { >>>> case SonOf(unowned Parent) >>>> case DaughterOf(unowned Parent) >>>> } >>>> >>>> The only current alternative is to have some intermediate reference type >>>> that itself holds the reference, akin to the old "Box" type that we used >>>> to use to work around enum limitations. E.g., this is our current >>>> cumbersome work-around: >>>> >>>> /// An unowned reference to a value, which is useful for maintaining >>>> parent-child relations through value types like enums >>>> public struct UnownedRef<T: AnyObject> { >>>> public unowned let value: T >>>> public init(_ value: T) { self.value = value } >>>> } >>>> >>>> enum ParentChild { >>>> case SonOf(UnownedRef<Parent>) >>>> case DaughterOf(UnownedRef<Parent>) >>>> } >>>> >>>> >>>> class Parent { >>>> lazy var son: Child = Child(parentChild: .SonOf(UnownedRef(self))) >>>> lazy var daughter: Child = Child(parentChild: >>>> .DaughterOf(UnownedRef(self))) >>>> deinit { print("deinit Foo") } >>>> } >>>> >>>> class Child { >>>> var parentChild: ParentChild >>>> init(parentChild: ParentChild) { >>>> self.parentChild = parentChild >>>> } >>>> >>>> deinit { print("deinit Child") } >>>> } >>>> >>>> The storage type of an enum would, of course, be limited to reference >>>> types, and when the storage class is weak, it would require that the >>>> stored type be Optional, just like when declaring a weak variable. >>>> >>>> What do people think? >>>> >>>> -Marc >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >> > _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
