Re-initializing lazy vars

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?

···

--
Rick Mann
rmann@latencyzero.com

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?

--
Rick Mann
rmann@latencyzero.com

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

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&gt;\).

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?

--
Rick Mann
rmann@latencyzero.com

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

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?

--
Rick Mann
rmann@latencyzero.com

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

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.

Joanna

···

--
Joanna Carter
Carter Consulting

Oops! forgot to add example code for resetting with non-optional public var :

public struct TestStruct
{
  private var _description: String?
  
  public var description: String
  {
    get
    {
      return _description ?? ""
    }
    set
    {
      _description = newValue
    }
  }
  
  mutating func resetDescription()
  {
    _description = nil
  }
}

Joanna

···

--
Joanna Carter
Carter Consulting