Lazy let: readonly lazy var

Hello,

Has there been a proposal for readonly lazy vars?

Here's a contrived example.

final class Object {
  private let x = 0
  private(set) lazy var y = x + 1

  init() {
    x = 2 // how to avoid this being possible? 
  }
}

Declaring y as private let y = x + 1 displays Cannot use instance member 'x' within property initializer; property initializers run before 'self' is available.

Declaring y as 'lazy' as private lazy let y = x + 1 displays 'lazy' cannot be used on a let.

The best approach so far is to declare y as private(set) lazy var y = x + 1. This has the advantage that at least the property is immutable outside of the instance. However, it is still mutable from within the class.

E.g.

  private let x = 0
  private(set) lazy var y = x + 1

  init() {
    y = 2
  }
}

print(Object().y)
// 2

in this example, how can the line y =2 become a compile error? It must be an omission from the Swift language, that lays great value in immutable properties. If it needs to be said at all, immutable properties make for code that is easier to reason able, due to the reduction of mutable state. That can help engineers introduce fewer bugs, someone everyone should support.

It's already not possible to assign a value to x in the initializer (or anywhere else) because x is a let constant that was already initialized to 0. This code already does NOT compile.

It's not a compilation error. Are you suggesting that it should be? In that case, make y a let constant.

Here's what you probably want:

final class Object {
    
    private let x = 0
    private let y: Int
    
    init() {
        self.y = x + 1
    }
    
}

Thank you for reviewing my code. What I had intended was

final class Object {
  private let x = 0
  private(set) lazy var y = x + 1

  init() {
    y = 2 // how to avoid this being possible?
  }
}

You see, y is 1, then y is 2, and there is nothing to prevent another update to y setting it to another value from inside this class. y is declared as lazy so as to increment the value of x. It seems like your approach of setting y in the initializer way work in this case.