[swift-evolution] [Review] SE-0030 Property Behaviors

Joe Groff jgroff at apple.com
Mon Feb 22 13:02:23 CST 2016

> On Feb 22, 2016, at 10:04 AM, Taras Zakharko via swift-evolution <swift-evolution at swift.org> wrote:
> I waned to write only a quick note, but in the end it became to verbose, so I will reiterate main points here for clarity, and point to the bottom of this mail for my original messy text with more details
> 1. I believe that property behaviors should support static data storage. This data storage exists per declared property (as opposed for per host instance for normal storage). This has clear use cases: space data storage using weak tables etc. 
> 2. The magic status of ‘initialValue’ can be resolved by introducing a per-declaration initialiser that captures the initialisation expression in a static (per-property) closure. This way, everything stays explicit, there is no per-instance overhead and also no magic. However, it is questionable whether this would actually be useful in practice. 
> 3. Should ‘initialValue’ remain ‘magical’, I’d prefer if it had similar treatment to other compiler directives. We already have #line etc, so why not also #initialValue? That will make it clear that compiler is inserting something for you. 

With behavior-controlled static storage and initialization, I don't think we'd need `initialValue` at all. The interesting variations of initialization could all be encoded as different combinations of static and instance init with @autoclosure:

// Bind an initial value evaluated at declaration time
var behavior eagerInLine {
  static init(initialValue: Value)
// Bind an initial value evaluated later
var behavior deferredInLine {
  static init(@autoclosure initialValue: () -> Value)
// Bind an initial value assigned during instance initialization
var behavior eagerInstance {
  init(initialValue: Value)

User-definable static storage opens up other potential use cases too, as you've noted.

>> On 20 Feb 2016, at 07:16, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>> In particular, note the point about runtime overhead. Behaviors are carefully designed to be basically equivalent to writing the same code yourself every time you need that semantic. If we weren't aiming for that, the design would be much simpler: we'd have an `init(initialValue:)` that could handle deferred initialization by using an `@autoclosure` and storing it in a property, for instance. But compared to writing the same thing yourself, that would waste memory on an extra property to store the closure, so we don't want to do that.
> Just a quick note about this: I think the overhead can be avoided if the closure is stored once per property declaration rather then per object instance. This is how Python does it, for instance: properties are simply objects that define two magic methods for getting and setting values on the instance. The property object itself is instantiated only once and stored as part of the class attribute list. I can imagine that something like this could be done for Swift property behavior as well.

You could say my prototype implementation does this, though the "property object" is a protocol conformance rather than a first-class object.


> E.g.
> var behavior lazy<Value>:Value {
>  var value: Value? = nil
>  static let initialValue: ()->Value  
>  // executed once per property declaration
>  static declare(@autoclosure initialiser: ()->Value) { 
>    // can only access static variables here
>    initialValue = initialiser
>  }
>  // optional, executed once per property host instantiation
> init() {
> }
> }
> In a way, Joe’s proposal already does this, albeit implicitly. A refinement to make this more explicit removes the magic and gives the programmer more control.  
> The question of course whether this mechanism will be useful at all, that is, whether everyone would just use the same boilerplate to capture their initialValues or whether that is some legitimate use case for this. I do not know :) If it is deemed that this is not useful, then I’d prefer if initialValue were a ‘magic’ compiler directive, e.g. #initialValue to mirror its similar status to #file and friends. 
> Nevertheless, I think that static properties should be allowed for behaviors. That could enable some very powerful features, e.g. using weak dictionaries for sparse data allocation or enumeration of all objects that have particular features). 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list