Раннее возвращение из void-func в Свифт?

Может кто-нибудь объяснить мне следующее поведение в Swift?

func test() -> Bool {
    print("1 before return")
    return false
    print("1 after return")
}


func test2() {
    print("2 before return")
    return
    print("2 after return")
}


test()
test2()

возвращает:

1 before return
2 before return
2 after return

Я ожидаю, что print("2 after return") никогда не будет выполняться, так как это после оператора return.

Есть ли что-то, что мне не хватает?

(протестировано с Swift 4/4.1 и Xcode 9.2/Xcode 9.3 beta 2)

Ответ 1

Это сложная вещь, Swift не требует полуколоней (они необязательно используются), это позволяет компилятору Swift автоматически выводить, должна ли следующая строка быть новой строкой или завершением для старой. print() - это функция, которая возвращает void. Значит, слово return print("something"). Так

return
print("Something")

может быть выведено как return print("something")

Ваше решение - написать

return;
print("Something")

Ответ 2

func test2() похож на func test2() -> Void

Итак, ваш код обрабатывается как

func test2() -> Void {
  print("2 before return")
  return print("2 after return")
}

Добавление точки с запятой после печати должно исправить ее.

func test2() -> Void {
  print("2 before return")
  return; print("2 after return")
}

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

func test2() {
  print("2 before return")
  return
  2
}

ошибка: неожиданное неволевое возвращаемое значение в функции void 2 ^

Ответ 3

Когда я попробовал это в IBM Swift Sandbox, я получил следующее предупреждение:

warning: expression following 'return' is treated as an argument of the 'return'
    print("2 after return")
    ^

что в значительной степени объясняет эту проблему. Свифт интерпретирует это так, как если бы вы написали:

return(print("2 after return"))

Выполняется инструкция печати и возвращается возвращаемое значение print ().

Добавление ; после возврата делает отдельный оператор

return;
print("2 after return")

а затем предупреждение будет:

warning: code after 'return' will never be executed
    print("2 after return")

Ответ 4

func noReturn() {...}

совпадает с

func noReturn() -> (Void) {...} //or func noReturn() -> ()

и поскольку print (...) имеет одну и ту же подпись, нормально звонить   return print (...) в функции void

Ответ 5

Ответ извлечен из вопроса:

Кажется, проблема в том, что swift не завершает функцию сразу же после оператора return в void-функции и использует последовательное значение void в качестве параметра функции и завершается, как ожидается, если она не void.

Код после возврата никогда не будет выполнен

[...]
return; // <- would return here

[...]
return () // <- would return here

[...]
return // <- would return here
let x = 42

Если Xcode будет работать надежно, это сообщение должно быть показано на следующих примерах:

Выражение после возврата обрабатывается как аргумент возврата

[...]
return
print("oh no") // <- would return here

[...]
return
myClosure("this feels wrong") // <- would return here and execute the function / closure

Эта проблема уже существует в Swift-bug-tracker с 2016 года: https://bugs.swift.org/browse/SR-2028