Как я могу использовать try с оператором объединения? - PullRequest
5 голосов
/ 06 марта 2019

Я пытаюсь присвоить значение x из функции f, которая принимает один параметр (строку) и выбрасывает.

Текущий объем бросков, поэтому я считаю, что do ... catch не требуется.

Я пытаюсь использовать try с оператором объединения ??, но я получаю эту ошибку: 'try' cannot appear to the right of a non-assignment operator.

guard let x = try f("a") ??
              try f("b") ??
              try f("c") else {
    print("Couldn't get a valid value for x")
    return
}

Если я изменю try на try?:

guard let x = try? f("a") ??
              try? f("b") ??
              try? f("c") else {
    print("Couldn't get a valid value for x")
    return
}

Я получаю предупреждение Left side of nil coalescing operator '??' has non-optional type 'String??', so the right side is never used и ошибку: 'try?' cannot appear to the right of a non-assignment operator.

Если я поставлю каждую попытку? в скобках:

guard let x = (try? f("a")) ??
              (try? f("b")) ??
              (try? f("c")) else {
    print("Couldn't get a valid value for x")
    return
}

Он компилируется, но x является необязательным, и я хотел бы, чтобы он был развернут.

если я уберу знаки вопроса:

guard let x = (try f("a")) ??
              (try f("b")) ??
              (try f("c")) else {
    print("Couldn't get a valid value for x")
    return
}

Я получаю ошибку Operator can throw but expression is not marked with 'try'.

Я использую Swift 4.2 (последняя версия Xcode на момент написания).

Как правильно сделать это, чтобы получить развернутое значение в x?

Обновление: * f() Тип возврата String ?. Я думаю, что тот факт, что это необязательная строка, важен.

1 Ответ

4 голосов
/ 06 марта 2019

Один try может охватывать все выражение, поэтому вы можете просто сказать:

  guard let x = try f("a") ?? f("b") ?? f("c") else {
    print("Couldn't get a valid value for x")
    return
  }

То же самое относится к try?:

  guard let x = try? f("a") ?? f("b") ?? f("c") else {
    print("Couldn't get a valid value for x")
    return
  }

Хотя обратите внимание, что в Swift 4.2 x будет String? из-за того, что вы применяете try? к уже необязательному значению, что дает вам необязательную двойную упаковку, которая guard let развернет только одну слой.

Чтобы исправить это, вы можете объединиться в nil:

  guard let x = (try? f("a") ?? f("b") ?? f("c")) ?? nil else {
    print("Couldn't get a valid value for x")
    return
  }

Но в Swift 5 это не нужно из-за SE-0230 , где try? f("a") ?? f("b") ?? f("c") будет автоматически сведен компилятором в одно необязательное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...