Just spent a while trying to figure out a bizarre, paranormal bug:
I had a function for testing physics components for a game. One entity was moving faster than the other despite being exactly the same.
Turns out that it was being added to the scene twice because code after a return was being executed:
You can replicate this in a Playground:
var wth = 0
func SwiftPlease() {
wth += 1
return
wth += 1 // ⚠️ Expression following 'return' is treated as an argument of the 'return'
}
SwiftPlease()
print(wth) // Can you guess what this will be?
I can almost see what's happening here, but why allow an argument for the return at all if the function's signature does not specify a return value?
1 Like
eimantas
(Eimantas)
2
Try adding semicolon after a return you should be fine.
1 Like
AlexanderM
(Alexander Momchilov)
3
I would be very surprised/disappointed if this fixes it.
@SubjugaterCephalopod Have you tried doing a clean build? I suspect your code's just running some old version before the return was put in.
+= returns Void, and you're free to explicitly return Void.
5 Likes
Lantua
5
Perhaps this should be a compiler warning. Since it's technically valid, but likely not something people would be doing.
Martin
(Martin R)
6
There is an warning, but it seems to be delayed.
I‘d be against a warning because I frequently use that in the else body of a guard statement. There is nothing wrong learning that several operators including = return Void and using that in combination with return.
To me this is a programmer mistake, not a bug, since in Swift there is always a return type, but for convenience it could be implicit. Not understanding this fact is a source of bugs.
4 Likes
Lantua
9
I’m quite interested as to why you’d do that instead of just using multi-line statements, or is it just purely stylistic choice?
I’d say it’s a rarely-used fact, and most programmer won’t ever need to think in terms of Void-returning function.
Anyhow, I don’t have a strong opinion on this matter. I know of the technicality of it (for a long time actually). I still feel that it’d be hard to read if I actually use it, but that’s about it.
This
.
This should be the else body from a guard statement.
// #1
return self.foo()
// #2
self.foo()
return
#2 feels redundant to me and therefore I prefer #1.
1 Like
sveinhal
(Svein Halvor Halvorsen)
11
In a lot of async code that take a completion handler, the completion handler is semantically like a (delayed) return value. You need it on every early return path.
guard condition else { return completion(nil) }
…neatly mirrors return nil in a synchronous function.
2 Likes
sveinhal
(Svein Halvor Halvorsen)
12
I would always have return and its argument on the same line though. Using a newline between the two would probably put me off.
AlanK
(Alan Kantz)
13
I am also fond of
return voidReturningFunction()
and would be dismayed to have it produce a warning, but I would not be sad to see
return
voidReturningFunction()
produce a warning. Does anyone have a use case for why it shouldn’t be discouraged? Assume we’re being conservative and no warning is produced for
return operand
+= otherOperand
6 Likes
That does produce a warning, and the warning is shown in the original post.
1 Like
idrougge
(Iggy Drougge)
15
I'm also an avid user of return funcThatReturnsVoid() in callbacks and guard clauses, but if this is a impediment for new Swift users, I would relent.