Are these `lazy` class property declarations semantically different?

class Foo1 {
    let val : Int = 42
    lazy var bar : Int = { expensiveOperation(self.val) }()
}

class Foo2 {
    let val : Int = 42
    lazy var bar : Int = expensiveOperation(self.val)
}

The first uses an explicit closure; the second does not. But they both compile and have (apparently) the same behavior.

How does the Swift compiler handle the second style of lazy? Is a closure implicitly wrapped around the RH expression, so it ends up being syntactic sugar for the first form? Or is a different mechanism used to delay the evaluation? Are there other capture semantics related to self that are different?

Defining and immediately calling a closure with a single expression is always entirely redundant. Just use the expression by itself. This applies whether you use the lazy keyword or not.

No, because it serves no purpose to wrap an expression in a closure and then immediately call it. Lazy properties are more complicated than that.

In general the closure is the more expressive notation because even with one expression in the body, it can be annotated with a capture list; the other can’t. Hence the question whether, in this case, lazy treats the two styles of notation the same in terms of the capture semantics of self.

2 Likes

If you do add a capture list, then the first form would be different from the first, but you didn't do that in your examples, so both forms have the same semantics.