Используйте "или" логику с несколькими операторами "if case" - PullRequest
0 голосов
/ 05 декабря 2018

Предположим, у меня есть регистр перечисления со связанным значением и две переменные этого типа:

enum MyEnum {
    case foo, bar(_ prop: Int)
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

Если я хочу проверить, соответствуют ли обе переменные общему случаю ссоответствующее значение, я могу сделать это с помощью запятой:

if case .bar = var1, case .bar = var2 {
    print("both are bar")
}

Но мне нужно проверить, соответствует ли либо регистр, с чем-то вроде этого:

if case .bar = var1 || case .bar = var2 {
    print("at least one is bar")
}

Однако, это не компилируется.Есть ли другой способ написать это, чтобы заставить логику работать?

Ответы [ 4 ]

0 голосов
/ 08 апреля 2019

Мое решение для такого рода вещей:

if [var1, var2] .contains (.bar) {

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

, если [.bar, .baz] .contains (var)

, но, действительно, если есть связанные значения, вы должны сделать ихуравнять и определить оператора.

0 голосов
/ 05 декабря 2018

Я полагаю, что if case и guard case являются синтаксическим сахаром и представляют собой лишь небольшую функцию, поддерживаемую компилятором для улучшения опыта разработчика.В первом случае вы используете последовательные условия, которые также являются языковой функцией для замены оператора &&, чтобы сделать код более читабельным.Когда вы используете операторы && или ||, компилятор ожидает получить два выражения, которые возвращают логические значения.case .bar = var1 само по себе не является выражением, которое могло бы жить в одиночестве, без некоторого контекста в Swift, поэтому оно не рассматривается как выражение, которое возвращает bool.

Подводя итог:

  • if case и guard case являются просто синтаксическим сахаром, работает вместе с if <expression>, <expression> синтаксисом

  • && и || - это просто логические операторы, которые в основном являются функциями, которые ожидают двух логических аргументов с обеих сторон.

Чтобы решить вашу проблему, используйте старый добрый оператор switch,Надеюсь, это поможет.

0 голосов
/ 05 декабря 2018

Я бы прибегнул к какому-либо свойству isBar в самом перечислении, чтобы тест "a или b" оставался читабельным:

enum MyEnum {
    case foo, bar(_ prop: Int)

    var isBar: Bool {
        switch self {
        case .bar: return true
        default: return false
        }
    }
}

let var1 = MyEnum.foo
let var2 = MyEnum.bar(1)

let eitherIsBar = var1.isBar || var2.isBar
0 голосов
/ 05 декабря 2018

Вы должны реализовать Equatable протокол для вашего перечисления:

extension MyEnum: Equatable {}
func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
    switch (lhs, rhs) {
        case (let .bar(prop1), let .bar(prop2)):
            return prop1 == prop2
        case (.foo, .foo):
        return true

     default:
         return false
    }
}

Тогда должен работать следующий код:

if var1 == .bar(1) || var2 == .bar(1) {
    print("at least one is bar")
}

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

switch (var1, var2) {
case (.bar, _), (_, .bar): print("at least one is bar")
default: break
}
...