Развертка опций в предопределенную переменную в условии защиты без создания новой константы

Оператор Swift guard позволяет вам разворачивать опции в новую константу и выполнять досрочный возврат, если присваивание не выполняется.

var someString:String? = "hello"
...
...  
guard let newString = someString 
   else {
     return
   }

...

Если я хочу развернуть необязательную переменную и установить ее в предопределенную необязательную переменную, я сначала разворачиваю новую константу (newString), а затем устанавливаю необязательную переменную после оператора защиты следующим образом:

var someString:String? = "hello"
var nonOptionalString:String = "bonjour"
...
...
guard let newString = someString 
   else {
     return
   }
nonOptionalString = newString

...

Есть ли способ установить предопределенную необязательную переменную в условии оператора Guard без создания новой константы? Что-то вроде следующего (что не работает)?

var someString:String? = "hello"
var nonOptionalString:String = "bonjour"
...
...
guard nonOptionalString = someString 
   else {
     return
   }
...

Если что-то подобное невозможно, существует ли основная философия дизайна языка Swift или техническая причина, почему этого не существует?


person GingerBreadMane    schedule 16.05.2017    source источник


Ответы (3)


Я бы просто проверил nil, а затем принудительно развернул бы, когда я знаю, что это не так:

var someString: String? = "hello"
let nonOptionalString: String       // note, you don't have to initialize this with some bogus value

guard someString != nil else { return }
nonOptionalString = someString!

Или, если someString был параметром какого-то метода или замыкания, вы можете развернуть оператор guard, используя то же имя переменной, что еще больше упростит жизнь:

func foo(someString: String?) {
    guard let someString = someString else { return }

    // now I can just use local `someString`, which is not optional anymore
}

Если вы отчаянно пытаетесь развернуть и выйти из-if-nil в одном выражении, вы теоретически можете написать функцию для развертки, если она может, или выдать ошибку, если она не может:

extension Optional {
    enum OptionalError: Error {
        case unwrapFailed
    }

    func unwrap<T>() throws -> T {
        if self == nil { throw OptionalError.unwrapFailed }
        return self as! T
    }
}

Затем вы можете сделать:

do {
    firstNonOptional  = try firstOptional.unwrap()
    secondNonOptional = try secondOptional.unwrap()
    thirdNonOptional  = try thirdOptional.unwrap()
} catch {
    return
}

Я думаю, что это ужасное излишество, но если вы отчаянно пытаетесь сократить его до одной строки на развертку, это один из способов сделать это.

person Rob    schedule 17.05.2017

Есть два способа сделать это.

  1. guard let someString = someString else { return }

Это просто проверяет значение с тем же именем переменной.

  1. guard someString != nil else { return }

Выполняя этот второй, вы даже можете объявить его с треском (!) Это будет «предопределено» до «необязательного» в некотором роде.

Итак, теперь вы можете объявить это так:

var someString:String! = "hello"

Я думаю, вы ищете именно это.

РЕДАКТИРОВАТЬ: А теперь вы можете использовать свой собственный пример.

guard someString != nil, nonOptional == someString else { return }
person Nebojsa Nadj    schedule 16.05.2017

Если смысл в том, чтобы сделать присваивание только в том случае, если присваивание возможно, напишите:

nonOptionalString = someString ?? nonOptionalString

Если вам действительно также нужно return, если присваивание невозможно, то просто напишите условие if/else:

if someString != nil {
    nonOptionalString = someString!
} else {
    return
}

Другими словами, перестаньте притворяться и просто говорите то, что имеете в виду.

person matt    schedule 16.05.2017