constant properties must always have a value before initialization completes. how about variable properties?

I saw below in The Swift Programming Language (Swift 3) > Properties

"You must always declare a lazy property as a variable (with the

var
keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy."


Constant properties must always have a value before initialization completes.

How about variable properties?

What are these different between conatant and variable during initializing?

Thank you so much

Variable properties must also have a value before initialization completes. ("Completes" means that a class invokes the superclass initializer, or a non-class type initializer returns.)


So 'let' and 'var' variables have the same behavior during initialization, except (IIRC) you can only assign to 'let' variables once (that is, only do it on one path through the code, though there might be multiple paths that you choose between), but you can assign to 'var' variables as many times as you wish.

"Variable properties must also have a value before initialization completes." and "Constant properties must always have a value beforeinitialization completes, and therefore cannot be declared as lazy."described in The Swift Programming Language (Swift 3)

Can we also say " Variable properties must always have a value beforeinitialization completes, and therefore cannot be declared as lazy."?


why I ask this question because I still don't know why constant properties cannot be declared as lazy.

Because that is how Swift was designed. Constants are constants, they don't change value after initialization.

Yes, I didn't really answer correctly, in terms of the "lazy" attribute.


The difference between 'let' and 'var' variables is that the value of a 'let' variable cannot change after initialization. Marking a property as "lazy" indicates that the value is set up when the variable is first referenced, which may be after initialization. Therefore, 'let' properties cannot be "lazy".


So, the difference is about when the value can change (including initial setup), not how many times it can change (including initial setup).


For that reason, it's better not to call it a "constant" property or variable. A constant property is one whose value can change only once (at initial setup), whether that's before or after the instance initialization.


AFAIK, the reason for the 'let'/'var' distinction being odd in this way has to do with memory coherency in multi-tasking environments. Properties or variables that are declared with 'let' will present a consistent value to all CPUs through all memory caches without any explicit cache control, and exhibit none of the subtle memory "aliasing" issues that cause difficulties in languages like C and Obj-C. IOW a 'let' property is 100% thread-safe, but a 'var' property does not come with that guarantee.

as I learned from The Swift Programming Language (Swift 3) the initialization process will do 2 things, create an instance and also give initial values to all its properties. In orther word, property is assigned its initial value during the initialization.

I am a Swift beginner so that I may get wrong understanding in the initialization process.


You said "A constant property is one whose value can change only once (at initial setup), whether that's before or after the instance initialization."

Could you have an example for "before the instance initialization" and an example for "after the instance initialization"?


By the way, culd you also give an example for "Marking a property as "lazy" indicates that the value is set up when the variable is first referenced, which may be after initialization."?


Thank you so much

By the way, culd you also give an example for "Marking a property as "lazy" indicates that the value is set up when the variable is first referenced, which may be after initialization."?

Here you go:

func returnF() -> Int {
    print("*** initialise `f` ***")
    return 6
}

class Foo {
    let a: Int = 1
    let b: Int
    var c: Int = 3
    var d: Int
    lazy var e: Int = 5
    lazy var f: Int = returnF()
    lazy var g: Int = {
        print("*** initialise `g` ***")
        return 7
    }()
    init() {
        self.b = 2
        self.d = 4
    }
}

let i = Foo()
print(i.a)
print(i.b)
print(i.c)
print(i.e)
print(i.f)
print(i.f)
print(i.g)
print(i.g)

This prints:

1
2
3
5
*** initialise `f` ***
6
6
*** initialise `g` ***
7
7

Note that the first accesses of

f
and
g
runs the lazy initialisation code (hence the printed messages), but the second accesses do not. Also note that the closure syntax for
g
is a common shortcut for multi-statement lazy initialisation without the need for a separate function.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I viewed and checked the said exaple very carefully, but it seems still not answer my question.

I think it may cause by which is initialized.

when executing "let i = Foo()" in line 23, Swift creates an instance for 'i', but at the time e,f,g do not is initialized yet due to "lazy"


when executing "print(i.e)" in line 27, e is first referenced so that e is initialized (get a initial value of 5 during the initialization of e) and then print '5'


when executing "print(i.f)" in line 28, f is first referenced so that f is initialized (catt returnF function to get a initial value of 6 during the initialization of f) and then print '6'.

NOTE: It ("print(i.f)" in line 28) is "during the initialization of f " instead of "after the initialization of f " so that this said example is not what I want to see.


The main purpose in this post is "why we cannot use lazy in constant property?". I would like to get an example that indicate a initial value already is assigned to the lazy property before the lazy property is first referenced. Because in this case the lazy property will is assigned a value again when the lazy property is first referenced, This will make the property mutable so that it will not allow lazy constant in Swift.


Could you give an example to indicate the said case?

>>Because in this case the lazy property will is assigned a value again when the lazy property is first referenced, This will make the property mutable so that it will not allow lazy constant in Swift.


Yes, exactly so.


But, initialization != initial value


It's a matter of terminology. Swift has a process called "initialization", which applies when an instance of a type is created. As part of initialization, the instance's properties are also initialized, and Swift has a rule that all properties must be initialized at the beginning of the instance initialization. This is true of Quinn's "Foo" example. All properties (including the lazy ones) are regarded as initialized during Foo's initializer.


However, all stored properties also start out with an initial value, which is something different. Lazy properties have an (unspecified) initial value, simply because they occupy memory, and the memory must contain something. It could be zero, or it could be garbage, it doesn't really matter because we will never find out what that value is — because as soon as we try, the lazy initialization will change the value to the correct thing.


So, a better mental picture for "lazy" properties would be that they are invisibly set to (say) zero bits during instance initialization, and re-set to a different value later. That's why they cannot be 'let'.


Or, it may help to think that initialization is a compile-time concept, while initial value is a run-time concept.

What QuinceyMorris said but also…

The way I’ve heard the Swift folks explain this (and please take note that I use Swift but I don’t work on it) is that the Swift memory model is defined such that

let
denotes a value that a) is set up before anyone sees it, and b) cannot possibly change. That’s why you can’t use
let
for lazy properties, read-only computed properties, and so on. In short,
let
has a specific semantic meaning within the memory model, it’s not a synonym for read-only.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
constant properties must always have a value before initialization completes. how about variable properties?
 
 
Q