> 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
