[swift-evolution] [proposal] Allow "let" for computed properties which only reference immutable data

Joe Groff jgroff at apple.com
Wed May 11 13:31:15 CDT 2016

> On May 11, 2016, at 11:02 AM, Haravikk <swift-evolution at haravikk.me> wrote:
>> On 11 May 2016, at 18:00, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>>> On May 11, 2016, at 8:34 AM, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
>>>> On May 11, 2016, at 10:26 AM, Sean Heber via swift-evolution <swift-evolution at swift.org> wrote:
>>>> I kind of agree with the logic of that, but imagine the following:
>>>> class Test {
>>>> let hello = “hello”
>>>> var subject = “world”
>>>> var phrase: String { return hello + “, “ + subject }
>>>> }
>>>> In this scenario, “subject” can be changed.. and that changes the result of “phrase”. Things like this are why computed properties are “var”.
>>> This example would still be required to be var because it accesses a var in its implementation.
>>> I like the idea of allowing this feature, but only in cases where the compiler can verify immutable semantics.  Having it may help drive other features that could expand the cases the compiler can verify.  That would be great as this is a direction I would like to see Swift take in the future.
>> Yeah, this is why we don't currently allow computed "let" properties. We'd only want to do so once we have the language facilities to ensure a computed 'let' property is immutable and has no observable side effects.
> Even if a “computed” property were immutable, do we really want to implicitly make it a constant as well? Take for example:
> class Test {
>     let a:[Int64]
>     let b:[Int64]
>     init(_ value:Int64) {
>         self.a = Array(count: 65536, repeatedValue: Int64(value))
>         self.b = Array(count: 65536, repeatedValue: Int64(value &+ 1))
>     }
>     var combined:[Int64] { return a + b }
> }
> Each of these arrays is 512kb, so storing a fixed value for the combined property would require another megabyte of space per instance of Test, but if the combined property is only infrequently called on some instances of Test, then it would be a waste of memory to precompute it, especially if you’re dealing with thousands of instances, with only a fraction of them calling the computed property. If you want to accelerate usage of the computed property then that’s what lazy variables are for, as you can delay the expensive combination until you actually need it.

Being constant doesn't need to imply "precomputed". I would expect a computed 'let' to still be computed on-demand. 'let' is more important as an API contract; you're guaranteeing to the user that an API won't produce different values if called on the same object at different times.


> The problem really is that the compiler can only do limited analysis about whether a computer property is used a lot, and in most cases it doesn’t care (it only really cares whether something is unused, as it can try to optimise it away), to make a good decision it would need to run the program with a realistic test-case an analysis memory overhead and performance impact of each method.
> So yeah, I’m not really sure of the advantage of this, unless the intention is purely to restrict what can be used within your computed property’s implementation, but I don’t think the compiler can realistically do much in the way of optimising stuff away as precomputed values need to be stored somewhere, which could mean making your type bigger, which begs the question of why you specified a computed value in the first place.
> I guess I’m just confused as to what the problem being solved would really be.

More information about the swift-evolution mailing list