Разделение нескольких условий с запятыми в Swift

Мы уже знаем, что несколько необязательных привязок могут использоваться в одном выражении if/guard, разделяя их запятыми, но не с && eg

// Works as expected
if let a = someOpt, b = someOtherOpt {
}
// Crashes
if let a = someOpt && b = someOtherOpt {
}

Играя с игровыми площадками, формат в стиле запятой также, похоже, работает для булевых условий, хотя я не могу найти это нигде. например

if 1 == 1, 2 == 2 {
}
// Seems to be the same as
if 1 == 1 && 2 == 2 {
}

Является ли это приемлемым методом оценки нескольких логических условий и является ли поведение , идентичное поведению && или они технически разные?

Ответ 1

На самом деле результат не тот. Скажем, что у вас есть 2 оператора в if и && между ними. Если в первом случае вы создадите let, используя необязательную привязку, вы не сможете увидеть его во втором выражении. Вместо этого, используя запятую, вы будете.

Пример запятой:

if let cell = tableView.cellForRow(at: IndexPath(row: n, section: 0)), cell.isSelected {
    //Everything ok
}

&& Пример:

if let cell = tableView.cellForRow(at: IndexPath(row: n, section: 0)) && cell.isSelected {
    //ERROR: Use of unresolved identifier 'cell'              
}

Надеюсь это поможет.

Ответ 2

В Swift 3 ключевое слово where в условии условия было заменено вместо запятой.

Поэтому утверждение вроде if 1 == 1, 2 == 2 {} говорит "если 1 равно 1, где 2 равно 2..."

Это, вероятно, легче читать условный оператор с && вместо ,, но результат тот же.

Подробную информацию об изменениях в Swift 3 можно найти в предложении Swift Evolution: https://github.com/apple/swift-evolution/blob/master/proposals/0099-conditionclauses.md

Ответ 3

Вот случай, когда они достаточно различны, чтобы требовать ,. Следующий код даст

"Я" захвачено закрытием до инициализации всех членов

class User: NSObject, NSCoding {

    public var profiles: [Profile] = []    
    private var selectedProfileIndex : Int = 0

    public required init?(coder aDecoder: NSCoder) {
        // self.profiles initialized here

        let selectedIndex : Int = 100
        if 0 <= selectedIndex && selectedIndex < self.profiles.count {  <--- error here
            self.selectedProfileIndex = selectedIndex
        }

        super.init()
    }

...
}

Это связано с определением && на Bool:

static func && (lhs: Bool, rhs: @autoclosure () throws -> Bool) rethrows -> Bool

selectedIndex < self.profiles.count в RHS попадает в замыкание.

Изменение && на , избавит от ошибки. К сожалению, я не уверен, как , определяется, но я думал, что это было интересно.

Ответ 4

https://docs.swift.org/swift-book/ReferenceManual/Statements.html#grammar_condition-list

Грамматика Swift говорит, что condition-list оператора if может состоять из нескольких condition разделенных запятыми ,

0Yrux.png

Простым условием может быть логическое expression, optional-binding-condition или другие вещи:

enter image description here

Таким образом, использование запятой для разделения нескольких выражений прекрасно.

Ответ 5

Когда шаблон соответствует ассоциированному значению в переключателе, это имеет значение при использовании , или &&. Один компилируется, другой нет (Swift 5.1). Это компилируется (&&):

enum SomeEnum {
    case integer(Int)
}

func process(someEnum: SomeEnum) {
    switch someEnum {
    // Compiles
    case .integer(let integer) where integer > 10 && integer < 10:
        print("hi")
    default:
        fatalError()
    }
}

Это не так (,):

enum SomeEnum {
    case integer(Int)
}

func process(someEnum: SomeEnum) {
    switch someEnum {
    // Compiles
    case .integer(let integer) where integer > 10, integer < 10:
        print("hi")
    default:
        fatalError()
    }
}

Ответ 6

Когда дело доходит до вычисления логических условий, разделенных запятыми, простой способ представить запятую - это пара или скобки. Итак, если у вас есть

if true, false || true {}

Это превращается в

if true && (false || true) {}