On Mon, Aug 8, 2016 at 6:16 PM, Rick Mann <rm...@latencyzero.com> wrote:
> > > On Aug 3, 2016, at 03:23 , Dan Loewenherz <d...@lionheartsw.com> wrote: > > > > On Wed, Aug 3, 2016 at 3:51 AM, Rick Mann via swift-users < > swift-users@swift.org> wrote: > > > > > On Aug 2, 2016, at 19:06 , Jordan Rose <jordan_r...@apple.com> wrote: > > > > > > I don’t think it makes sense to do this. A protocol cannot control how > a particular property is implemented (stored or computed), and any > conforming type must initialize all of its stored properties before > returning from its own initializer. (You can’t write an initializer in a > protocol that doesn’t delegate to another initializer because you don’t > know what other stored properties the conforming type might have.) > > > > > > Given that the protocol can’t control how the property gets > initialized, it doesn’t make sense to allow the protocol to "set the > variable, but only in the initializer”. > > > > Really? It seems pretty natural for a conforming type to set a property > once in the initializer, and it's immutable from then on out. I can do that > quite cleanly with classes, but there's no way (that I know) to describe > this using protocols. Ideally, I could just do: > > > > protocol > > Element > > { > > let uuid: UUID > > } > > > > which implies that all conforming types must initialize that value on > creation, or provide a getter with let semantics (the latter might be too > easy to break, and could be disallowed, requiring conforming types to > create storage for the property and set it in init()). > > > > The compiler only knows as much as you tell it, and when you define a > protocol and set it as { get } only, it's not going to let you set that > property in a protocol extension for a protocol that doesn't expect a > setter. Why or how would the compiler let you? > > > > The solution is to create your init implementation in a concrete type, > and define the let property in there as well. E.g. > > > > protocol Element { > > var uuid: UUID { get } > > } > > > > class Item: Element { > > let uuid: UUID > > > > init(uuid: UUID) { > > self.uuid = uuid > > } > > } > > > > Because then Element.uuid doesn't have let semantics. It can't be set, but > it's not constant. > It's unavoidable. In this case, whether a variable can be set only once or more than once is an implementation detail that you need to deal with in a concrete type. What you're looking for would be a new feature, like "setonce". But let's assume the language designers added that in, how would it work? protocol Element { var uuid: UUID { get setonce } } And somewhere in your codebase, you have something like this: for element in elements { element.uuid = UUID() } The problem is that whether or not "uuid" is set can only be decided at runtime. As a result, the type checker can't tell you if you're making a mistake. It has no way to know if you've already set the value of "uuid" somewhere else, e.g., through a UI interaction, or some other code that's based on state. The result is that if "uuid" happens to already be set, you'd get a runtime error, which would be a very un-Swift-y thing to do, or every assignment would need to get wrapped in some sort of error handler. Dan
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users