Googling for the answer, it seemed some versions of Swift supported setting a lazy var property to nil, such that the next time it's accessed, the initializer would be run again.
But I just tried this in a playground in Swift 4 and it doesn't work.
It sure seems to me like it should work. What's the reasoning for the current behavior?
I don't know. IIRC (big if), though, there was talk of adding support for "property behaviors"(?). Resetting lazy vars probably would've been one of them, and if so, it probably got pulled so that we wouldn't risk breaking source compatibility later by adding a consistent syntax for other behaviors. I think. I wish I could remember who'd brought up the idea... they'd probably know straight away if that's what happened.
- Dave Sweeris
···
On Oct 19, 2017, at 5:40 PM, Rick Mann via swift-users <swift-users@swift.org> wrote:
Googling for the answer, it seemed some versions of Swift supported setting a lazy var property to nil, such that the next time it's accessed, the initializer would be run again.
But I just tried this in a playground in Swift 4 and it doesn't work.
It sure seems to me like it should work. What's the reasoning for the current behavior?
It's not directly related to property behaviors. It was a bug that only worked with ImplicitlyUnwrappedOptional properties; we patched the type checker bug that led to it being allowed and didn't even notice until someone brought it up (SR-5172 <https://bugs.swift.org/browse/SR-5172>\).
It would be possible to introduce this as an actual language feature even without the full property behaviors model, but we wouldn't want to just spell it 'lazy'. Maybe 'lazy_resettable' or something. And even though I say this, it's probably unlikely that such a proposal would get through swift-evolution in the Swift 5 timeframe.
Meanwhile, it's always possible to implement it by hand, though I can see how that'd be annoying if you were relying on this and previously got it with a single '!'.
class LazyResettableTest {
private func fooInitial() -> String { return "initial value" }
private var fooStorage: String?
var foo: String! {
get {
if fooStorage == nil { fooStorage = fooInitial() }
return fooStorage
}
set {
fooStorage = newValue
}
}
}
Jordan
···
On Oct 19, 2017, at 19:59, David Sweeris via swift-users <swift-users@swift.org> wrote:
I don't know. IIRC (big if), though, there was talk of adding support for "property behaviors"(?). Resetting lazy vars probably would've been one of them, and if so, it probably got pulled so that we wouldn't risk breaking source compatibility later by adding a consistent syntax for other behaviors. I think. I wish I could remember who'd brought up the idea... they'd probably know straight away if that's what happened.
- Dave Sweeris
On Oct 19, 2017, at 5:40 PM, Rick Mann via swift-users <swift-users@swift.org> wrote:
Googling for the answer, it seemed some versions of Swift supported setting a lazy var property to nil, such that the next time it's accessed, the initializer would be run again.
But I just tried this in a playground in Swift 4 and it doesn't work.
It sure seems to me like it should work. What's the reasoning for the current behavior?
It just seems so obvious to create-if-nil, and makes it nice to reset stuff that should be re-created. In my case, after my NSURLSession gets invalidated, I wanted to set the property to nil, and next time a session was needed, it would just get created.
Sure, I can implement this myself, but ugh.
···
--
Rick Mann
rmann@latencyzero.com
On Oct 20, 2017, at 17:58, Jordan Rose <jordan_rose@apple.com> wrote:
It's not directly related to property behaviors. It was a bug that only worked with ImplicitlyUnwrappedOptional properties; we patched the type checker bug that led to it being allowed and didn't even notice until someone brought it up (SR-5172).
It would be possible to introduce this as an actual language feature even without the full property behaviors model, but we wouldn't want to just spell it 'lazy'. Maybe 'lazy_resettable' or something. And even though I say this, it's probably unlikely that such a proposal would get through swift-evolution in the Swift 5 timeframe.
Meanwhile, it's always possible to implement it by hand, though I can see how that'd be annoying if you were relying on this and previously got it with a single '!'.
class LazyResettableTest {
private func fooInitial() -> String { return "initial value" }
private var fooStorage: String?
var foo: String! {
get {
if fooStorage == nil { fooStorage = fooInitial() }
return fooStorage
}
set {
fooStorage = newValue
}
}
}
Jordan
On Oct 19, 2017, at 19:59, David Sweeris via swift-users <swift-users@swift.org> wrote:
I don't know. IIRC (big if), though, there was talk of adding support for "property behaviors"(?). Resetting lazy vars probably would've been one of them, and if so, it probably got pulled so that we wouldn't risk breaking source compatibility later by adding a consistent syntax for other behaviors. I think. I wish I could remember who'd brought up the idea... they'd probably know straight away if that's what happened.
- Dave Sweeris
On Oct 19, 2017, at 5:40 PM, Rick Mann via swift-users <swift-users@swift.org> wrote:
Googling for the answer, it seemed some versions of Swift supported setting a lazy var property to nil, such that the next time it's accessed, the initializer would be run again.
But I just tried this in a playground in Swift 4 and it doesn't work.
It sure seems to me like it should work. What's the reasoning for the current behavior?
It just seems so obvious to create-if-nil, and makes it nice to reset stuff that should be re-created. In my case, after my NSURLSession gets invalidated, I wanted to set the property to nil, and next time a session was needed, it would just get created.
The only thing I would query with the whole concept of resetting an implicitly unwrapped optional var is, with a simple example struct :
public struct TestStruct
{
private var _description: String?
public var description: String!
{
get
{
return _description ?? ""
}
set
{
_description = newValue
}
}
}
… test code would be :
{
var test = TestStruct()
test.description = nil
let str: String = test.description
}
The idea of setting a var to nil and then getting a valid object back seems a bit anachronistic.
I think I would rather add an explicit "reset" method.