Proposal: Auto-implemented computed properties

Certain languages allow the programmer to avoid creating backing variables
for getters and setters by using this syntax:

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double {
        get
        set
    }
    // alternatively var x: Double { get; set }
}

and generating code equivalent to this:

class Foo {
    init(x: Double) {
        _x = x
    }
    var _x: Double
    var x: Double {
        get {
            return _x
        }
        set {
            _x = newValue
        }
    }
}

This notation decreases verbosity and reduces the chance of incorrectly
implementing the pattern.

In the following case, the computed property 'x' can only be set in the
initializer.

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double { get }
}

Alternatively, the following syntax can be used to avoid using an
initializer:

class Foo {
    var x: Double { get } = 1.0
}

Before looking into the nuances of this syntax (regarding struct/enum
properties, access control, attributes, etc.) I would like to ask the
community if this feature would be a good fit for Swift.

···

--
Nathan

Certain languages allow the programmer to avoid creating backing variables for getters and setters by using this syntax:

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double {
        get
        set
    }
    // alternatively var x: Double { get; set }
}

and generating code equivalent to this:

class Foo {
    init(x: Double) {
        _x = x
    }
    var _x: Double
    var x: Double {
        get {
            return _x
        }
        set {
            _x = newValue
        }
    }
}

Hi Nathan,

How is this different than just declaring “var x : Double”? It is an important part of swift’s design that stored and computed properties are equivalent to external uses of an API.

-Chris

···

On Dec 11, 2015, at 11:20 AM, Nathan Yee via swift-evolution <swift-evolution@swift.org> wrote:

This notation decreases verbosity and reduces the chance of incorrectly implementing the pattern.

In the following case, the computed property 'x' can only be set in the initializer.

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double { get }
}

Alternatively, the following syntax can be used to avoid using an initializer:

class Foo {
    var x: Double { get } = 1.0
}

Before looking into the nuances of this syntax (regarding struct/enum properties, access control, attributes, etc.) I would like to ask the community if this feature would be a good fit for Swift.

--
Nathan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

Why not just use `let`?

Stephen

···

On Fri, Dec 11, 2015 at 2:20 PM, Nathan Yee via swift-evolution < swift-evolution@swift.org> wrote:

In the following case, the computed property 'x' can only be set in the
initializer.

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double { get }
}

1 Like

I’m wondering what the actual use of this is. Why not just write:

class Foo {
  init(x: Double) {
    self.x = x
  }

  var x: Double
}

Regards,

Nicky

···

On 11 dec. 2015, at 20:20, Nathan Yee via swift-evolution <swift-evolution@swift.org> wrote:

Certain languages allow the programmer to avoid creating backing variables for getters and setters by using this syntax:

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double {
        get
        set
    }
    // alternatively var x: Double { get; set }
}

and generating code equivalent to this:

class Foo {
    init(x: Double) {
        _x = x
    }
    var _x: Double
    var x: Double {
        get {
            return _x
        }
        set {
            _x = newValue
        }
    }
}

This notation decreases verbosity and reduces the chance of incorrectly implementing the pattern.

In the following case, the computed property 'x' can only be set in the initializer.

class Foo {
    init(x: Double) {
        self.x = x
    }
    var x: Double { get }
}

Alternatively, the following syntax can be used to avoid using an initializer:

class Foo {
    var x: Double { get } = 1.0
}

Before looking into the nuances of this syntax (regarding struct/enum properties, access control, attributes, etc.) I would like to ask the community if this feature would be a good fit for Swift.

--
Nathan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Of course in this case the property should have both getter and setter. With only getter it doesn't make sense.

Also It will be a good idea to allow an additional code in a setter to process a new value. e.g.

var myProperty: Int {
    get   // Empty getter automatically creates a backup property
            //  to store value and returns in in getter
    set {
         // Firstly the new value is copied to backup property
        processValue(value: newValue) 
    }

}

It sounds like you are asking about being able to elide the getter and have it auto-generated. This is a valid request, and should be in a new thread. You should not resurrect 3 year old threads, but should link back to them in your own thread, instead.

1 Like

Why not use willSet/didSet for this?

var myProperty: Int {
  willSet {
    processValue(value: newValue)
  }
}
1 Like

@ suyashsrijan: It's possible. But having that all a setter appears to be more convenient and intuitive.

Well, I could get confused by the title. To me this is what 'auto-implement computed property' about. BTW C# and Kotlin do something similar, but with Swift concept it can be done much better.

I am taking about the example you mentioned - in that example, all you're doing is passing the new value to a method, for that you can simply use willSet/didSet. Do you have a real-world example where what you're suggesting would make sense?

1 Like

The idea is to avoid inventing name for backup variable. Example

 private var myBackUpProperty: Int!

 internal var myProperty: Int {
      get { return  myBackUpProperty    }
      set { myBackUpProperty = newValue }
 }

With auto-generated properties you can just write

 internal var myProperty: Int {
       get 
       set 
 }

where backup field is created automatically.

If you want additional operations in 'set` you can also do it:

 internal var myProperty: Int {
       get 
       set {   processNewValue(value: newValue) }
 }

However this is not the main point in suggestion

How is the functionality offered by willSet and didSet not sufficient?

Your example of

internal var myProperty: Int { get set }

Is already what

internal var myProperty: Int

means.

2 Likes

Yes, but you still haven't explained what the advantage would be.

internal var myProperty: Int {
  get 
  set { processNewValue(value: newValue) }
}

can be rewritten as

internal var myProperty: Int {
  willSet { processNewValue(value: newValue) }
}

Without getter and setter the code will not compile. Error:

Variable 'self.myProperty' used before being initialized

class M {
    internal var myProperty: Int = 0 { willSet { processNewValue(value: newValue) } }

    func processNewValue(value: Int) {}
}

You have to initialize the property, but it compiles just fine. It might help if you provided more context.

4 Likes