early return from a void-func in Swift?

2020-02-28 02:39发布

Can someone explain me the following behaviour in 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()

returns:

1 before return
2 before return
2 after return

I would expect that print("2 after return") would never be executed since it is after a return statement.

Is there something I am missing?

(tested with Swift 4 / 4.1 & Xcode 9.2 / Xcode 9.3 beta 2)

标签: swift
5条回答
别忘想泡老子
2楼-- · 2020-02-28 03:00

It is a tricky thing, Swift doesn't require semi-colons (they are optionally used), this makes Swift compiler automatically deduce whether is the next line should be a new line, or a completion for the old one. print() is a function that returns void. So the word return print("something"), is valid. So

return
print("Something")

could be deduced as return print("Something")

Your solution is to write

return;
print("Something")
查看更多
beautiful°
3楼-- · 2020-02-28 03:05

func test2() is similar to func test2() -> Void

So your code gets treated as,

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

Adding semicolon after print should fix it.

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

You can also see the error if you place value type after return line and you will understand more,

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

error: unexpected non-void return value in void function 2 ^

查看更多
我命由我不由天
4楼-- · 2020-02-28 03:14

When I tried this in the IBM Swift Sandbox I got the following warning:

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

which pretty much explains the issue. Swift is interpreting it as if you had written:

return(print("2 after return"))

The print statement is executed and the return value of the print () is returned.

Adding ; after the return makes that a separate statement

return;
print("2 after return")

and then the warning becomes:

warning: code after 'return' will never be executed
    print("2 after return")
查看更多
【Aperson】
5楼-- · 2020-02-28 03:15

Answer extracted from question:

It seems the problem is, that swift does not exit the function instantly on a return statement in a void function and uses the consecutive void value as the function parameter and terminates as expected if it is non-void.

Code after 'return' will never be executed

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

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

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

If Xcode would work reliably this message should be shown on the next examples:

Expression following 'return' is treated as an argument of the 'return'

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

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

This issue is already in the Swift-bug-tracker since 2016: https://bugs.swift.org/browse/SR-2028

查看更多
Anthone
6楼-- · 2020-02-28 03:20
func noReturn() {...}

is the same as

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

and since print(...) has the same signature it is ok to call return print(...) in a void function

查看更多
登录 后发表回答