Providing a default value for an Optional in Swift?

后端 未结 4 1978
傲寒
傲寒 2020-11-29 17:57

The idiom for dealing with optionals in Swift seems excessively verbose, if all you want to do is provide a default value in the case where it\'s nil:

if let         


        
相关标签:
4条回答
  • 2020-11-29 18:37

    if you wrote:

    let result = optionalValue ?? 50
    

    and optionalValue != nil then result will be optional too and you will need unwrap it in future

    But you can write operator

    infix operator ??? { associativity left precedence 140 }
    
    func ???<T>(optLeft:T?, right:T!) -> T!
    {
        if let left = optLeft
        {
            return left
        }
        else { return right}
    }
    

    Now you can:

     let result = optionalValue ??? 50
    

    And when optionalValue != nil then result will be unwraped

    0 讨论(0)
  • 2020-11-29 18:40

    Update

    Apple has now added a coalescing operator:

    var unwrappedValue = optionalValue ?? defaultValue
    

    The ternary operator is your friend in this case

    var unwrappedValue = optionalValue ? optionalValue! : defaultValue
    

    You could also provide your own extension for the Optional enum:

    extension Optional {
        func or(defaultValue: T) -> T {
            switch(self) {
                case .None:
                    return defaultValue
                case .Some(let value):
                    return value
            }
        }
    }
    

    Then you can just do:

    optionalValue.or(defaultValue)
    

    However, I recommend sticking to the ternary operator as other developers will understand that much more quickly without having to investigate the or method

    Note: I started a module to add common helpers like this or on Optional to swift.

    0 讨论(0)
  • 2020-11-29 18:50

    The following seems to work

    extension Optional {
        func getOrElse<T>(defaultValue: T) -> T {
            if let value = self? {
                return value as T
            } else {
                return defaultValue
            }
        }
    }
    

    however the need to cast value as T is an ugly hack. Ideally, there should be a way to assert that T is the same as the type contained in the Optional. As it stands, type inferencing sets T based on the parameter given to getOrElse, and then fails at runtime if this does not match the Optional and the Optional is non-nil:

    let x: Int?
    
    let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414
    
    let a: Int? = 5
    
    let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double
    
    0 讨论(0)
  • 2020-11-29 19:00

    As of Aug 2014 Swift has coalescing operator (??) that allows that. For example, for an optional String myOptional you could write:

    result = myOptional ?? "n/a"
    
    0 讨论(0)
提交回复
热议问题