Enforce non-nil assignment to an implicitly unwrapped optional property?


(Glen Huang) #1

I want to define a property for a struct/class that is nil after initialization, but later is guaranteed to have a value after I manually assign to it. I think implicitly unwrapped optional property is designed specifically for that.

However, the problem arises when it comes to how do I enforce that I never mistakenly assign nil to this property?

struct Foo {
    var name: String!
}
var foo = Foo()

I can do foo.name = nil and it will compile just fine.

I guess I could do a run-time check with something like:

struct Foo {
    var name: String! {
        willSet {
            if newValue == nil {
                fatalError("nil isn't allowed")
            }
        }
    }
}

But it feels ugly, and seems to be something checkable at compile time.

I could define a new setter method:

struct Foo {
    private(set) var name: String!
    mutating func setName(_ name: String) {
        self.name = name
    }
}

But it feel tedious. Enforcing non-nil assignment probably fits 90% of the use cases of IUOs, since that’s basically their definition. Having to deviate from direct assignment syntax in usage and also define a new setter method for the majority cases seems unfortunate.

I wonder if it’s desirable to define an attribute or something to ask the compiler to only allow non-optionals to be assigned to IUO properties?


(Glen Huang) #2

Anyone has any thoughts on this?

···

On 16 Jul 2017, at 3:46 PM, Glen Huang via swift-evolution <swift-evolution@swift.org> wrote:

I want to define a property for a struct/class that is nil after initialization, but later is guaranteed to have a value after I manually assign to it. I think implicitly unwrapped optional property is designed specifically for that.

However, the problem arises when it comes to how do I enforce that I never mistakenly assign nil to this property?

struct Foo {
   var name: String!
}
var foo = Foo()

I can do foo.name = nil and it will compile just fine.

I guess I could do a run-time check with something like:

struct Foo {
   var name: String! {
       willSet {
           if newValue == nil {
               fatalError("nil isn't allowed")
           }
       }
   }
}

But it feels ugly, and seems to be something checkable at compile time.

I could define a new setter method:

struct Foo {
   private(set) var name: String!
   mutating func setName(_ name: String) {
       self.name = name
   }
}

But it feel tedious. Enforcing non-nil assignment probably fits 90% of the use cases of IUOs, since that’s basically their definition. Having to deviate from direct assignment syntax in usage and also define a new setter method for the majority cases seems unfortunate.

I wonder if it’s desirable to define an attribute or something to ask the compiler to only allow non-optionals to be assigned to IUO properties?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Rod Brown) #3

Implicitly unwrapped optionals are often used when the optional system is a little complicated around one of your variables.

Some of those times are variables that are nil-resettable (where you set nil, and it internally does something to use that as a reset case) or initialisation issues where you can’t know a variable at prior to the initialisation, but can get it out. But these are just two examples.

I think trying to work more on tying people’s hands with this attribute specifically designed to handle edge cases seems a little… concerning.

It might make more sense to use a computed property covering the internal property completely if you need this behaviour?

···

On 19 Jul 2017, at 3:31 pm, Glen Huang via swift-evolution <swift-evolution@swift.org> wrote:

Anyone has any thoughts on this?

On 16 Jul 2017, at 3:46 PM, Glen Huang via swift-evolution <swift-evolution@swift.org> wrote:

I want to define a property for a struct/class that is nil after initialization, but later is guaranteed to have a value after I manually assign to it. I think implicitly unwrapped optional property is designed specifically for that.

However, the problem arises when it comes to how do I enforce that I never mistakenly assign nil to this property?

struct Foo {
  var name: String!
}
var foo = Foo()

I can do foo.name = nil and it will compile just fine.

I guess I could do a run-time check with something like:

struct Foo {
  var name: String! {
      willSet {
          if newValue == nil {
              fatalError("nil isn't allowed")
          }
      }
  }
}

But it feels ugly, and seems to be something checkable at compile time.

I could define a new setter method:

struct Foo {
  private(set) var name: String!
  mutating func setName(_ name: String) {
      self.name = name
  }
}

But it feel tedious. Enforcing non-nil assignment probably fits 90% of the use cases of IUOs, since that’s basically their definition. Having to deviate from direct assignment syntax in usage and also define a new setter method for the majority cases seems unfortunate.

I wonder if it’s desirable to define an attribute or something to ask the compiler to only allow non-optionals to be assigned to IUO properties?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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


#4

Another valid reason to nullify implicitly unwrapped optional would be to free up some memory. I don’t think we want to disallow this behavior.

If you really need to be unable to assign nil to an implicitly unwrapped optional, you can fake it using this code. S.value acts like an implicitly unwrapped optional, except that the compiler won’t let you assign an optional to it.

struct S {
  struct T {
    var value: Int
  }
  
  private var t: T?
  var value: Int {
    get { return self.t!.value }
    set {
      if self.t == nil {
        self.t = T(value: newValue)
      } else {
        self.t!.value = newValue
      }
    }
  }
}

···

On Jul 19, 2017, at 8:07 AM, Rod Brown via swift-evolution <swift-evolution@swift.org> wrote:

Implicitly unwrapped optionals are often used when the optional system is a little complicated around one of your variables.

Some of those times are variables that are nil-resettable (where you set nil, and it internally does something to use that as a reset case) or initialisation issues where you can’t know a variable at prior to the initialisation, but can get it out. But these are just two examples.

I think trying to work more on tying people’s hands with this attribute specifically designed to handle edge cases seems a little… concerning.

It might make more sense to use a computed property covering the internal property completely if you need this behaviour?

On 19 Jul 2017, at 3:31 pm, Glen Huang via swift-evolution <swift-evolution@swift.org> wrote:

Anyone has any thoughts on this?

On 16 Jul 2017, at 3:46 PM, Glen Huang via swift-evolution <swift-evolution@swift.org> wrote:

I want to define a property for a struct/class that is nil after initialization, but later is guaranteed to have a value after I manually assign to it. I think implicitly unwrapped optional property is designed specifically for that.

However, the problem arises when it comes to how do I enforce that I never mistakenly assign nil to this property?

struct Foo {
var name: String!
}
var foo = Foo()

I can do foo.name = nil and it will compile just fine.

I guess I could do a run-time check with something like:

struct Foo {
var name: String! {
     willSet {
         if newValue == nil {
             fatalError("nil isn't allowed")
         }
     }
}
}

But it feels ugly, and seems to be something checkable at compile time.

I could define a new setter method:

struct Foo {
private(set) var name: String!
mutating func setName(_ name: String) {
     self.name = name
}
}

But it feel tedious. Enforcing non-nil assignment probably fits 90% of the use cases of IUOs, since that’s basically their definition. Having to deviate from direct assignment syntax in usage and also define a new setter method for the majority cases seems unfortunate.

I wonder if it’s desirable to define an attribute or something to ask the compiler to only allow non-optionals to be assigned to IUO properties?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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