An implicit return for guard


(Yarden Eitan) #1

Dear community,

While using ‘guard’ with much appreciation, I noticed a few cases where I
would of hoped for better and more concise code.

As of now, you receive a compiler error if your guard statement does not
provide an ending statement such as return/break/etc. at the end.
It is informative, but in many cases such a statement makes the code
repetitive and less concise.

As an example of cases where there are multiple guards done sequentially to
avoid very nested and unclear ‘if's:

guard let resp = response as? HTTPURLResponse else {
    failure(…)
    return
}

guard let resp.statusCode == 200 else {
    failure(…)
    return
}

guard let respData = data else {
    failure(…)
    return
}

guard let res = parse(respData) else {
    failure(…)
    return
}

success(…)

As you can see in this example, while the different failures can (and
should) provide different information for completion, we always have to add
a repetitive return after them.

My proposal is to allow for an implicit return when no ending statement is
provided. We could take this one step further and have the compiler aware
of it’s most inner scope and see if it is a while loop for example and
implicitly allow a break. But I think at least as a first step, by having
an implicit “return” we are saving the repetitiveness on many cases where
there are multiple guard statements and the return from them is obvious.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).

Glad to hear your thoughts on the matter.

Best,
Yarden


Inferred return for guard statement
(Xiaodi Wu) #2

This has been suggested several times before. See the conversations below:

http://article.gmane.org/gmane.comp.lang.swift.evolution/11563/

http://article.gmane.org/gmane.comp.lang.swift.evolution/6770/

···

On Mon, Jun 20, 2016 at 01:30 Yarden Eitan via swift-evolution < swift-evolution@swift.org> wrote:

Dear community,

While using ‘guard’ with much appreciation, I noticed a few cases where I
would of hoped for better and more concise code.

As of now, you receive a compiler error if your guard statement does not
provide an ending statement such as return/break/etc. at the end.
It is informative, but in many cases such a statement makes the code
repetitive and less concise.

As an example of cases where there are multiple guards done sequentially
to avoid very nested and unclear ‘if's:

guard let resp = response as? HTTPURLResponse else {
    failure(…)
    return
}

guard let resp.statusCode == 200 else {
    failure(…)
    return
}

guard let respData = data else {
    failure(…)
    return
}

guard let res = parse(respData) else {
    failure(…)
    return
}

success(…)

As you can see in this example, while the different failures can (and
should) provide different information for completion, we always have to add
a repetitive return after them.

My proposal is to allow for an implicit return when no ending statement is
provided. We could take this one step further and have the compiler aware
of it’s most inner scope and see if it is a while loop for example and
implicitly allow a break. But I think at least as a first step, by having
an implicit “return” we are saving the repetitiveness on many cases where
there are multiple guard statements and the return from them is obvious.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).

Glad to hear your thoughts on the matter.

Best,
Yarden

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Zubarev) #3

@implicitreturn guard a = b else { print(“foo”) }
Isn’t that just the same? I mean now you even write more boilerplate then bebore.

How does your return type look, what are you trying to solve?

···

--
Adrian Zubarev
Sent with Airmail

Am 20. Juni 2016 um 08:30:39, Yarden Eitan via swift-evolution (swift-evolution@swift.org) schrieb:

@implicitreturn guard a = b else { print(“foo”) }


#4

...

My proposal is to allow for an implicit return when no ending statement is provided. We could take this one step further and have the compiler aware of it’s most inner scope and see if it is a while loop for example and implicitly allow a break. But I think at least as a first step, by having an implicit “return” we are saving the repetitiveness on many cases where there are multiple guard statements and the return from them is obvious.

A 'guard' in a loop can commonly be used with either 'continue' or 'break', the compiler would not be able to guess your intent. And whatever default would be selected, it would be the wrong one for many scenarios.

The 'return' is an important keyword which, I think, should not be obfuscated as one often need to quickly find all exit point of a function, when debugging/analyzing code.

This goes along the line of the Swift “switch” statement, which doesn’t follow it’s predecessors and force a “break” but rather it is already implicitly there.

If you bring the consistency card, I would be more on the page of making 'break' mandatory and explicit in the 'switch'.

Dany

···

Le 20 juin 2016 à 02:30, Yarden Eitan via swift-evolution <swift-evolution@swift.org> a écrit :

If this proposal is too much of a leap, an alternative is to allow an implicit return but provide a warning (not an error). This warning can be suppressed using an @implicitreturn prefix to the guard statement or something along those lines (@implicitreturn guard a = b else { print(“foo”) } ).


(Yarden Eitan) #5

Adrian: I would prefer to not have it at all. But this is a better
alternative than a brand new line declaring a return, and nothing else.
This is inline and part of the ‘guard’ declaration (better context), and
definitely better than having a warning stay in your codebase.

Putting the code clarity aside, having a compiler error for a non-returned
guard seems like an overkill, and different that the other Swift
implementations (such as Switch that doesn’t need a break to not fall
through).

Xiaodi: Thank you for the links. Was an actual proposal ever formed for
this, or was it decided not to move forward?

Yarden

···

On June 20, 2016 at 1:33:54 AM, Adrian Zubarev via swift-evolution ( swift-evolution@swift.org) wrote:

@implicitreturn guard a = b else { print(“foo”) }

Isn’t that just the same? I mean now you even write more boilerplate then
bebore.

How does your return type look, what are you trying to solve?

--
Adrian Zubarev
Sent with Airmail

Am 20. Juni 2016 um 08:30:39, Yarden Eitan via swift-evolution (
swift-evolution@swift.org) schrieb:

@implicitreturn guard a = b else { print(“foo”) }

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #6

On the contrary, having a compiler error for a guard body that doesn't exit
the scope is the very point of having guard.

The links were for your review because the discussion on this idea has been
extensive and both times reached consensus that this is not a workable idea.

···

On Mon, Jun 20, 2016 at 09:12 Yarden Eitan via swift-evolution < swift-evolution@swift.org> wrote:

Adrian: I would prefer to not have it at all. But this is a better
alternative than a brand new line declaring a return, and nothing else.
This is inline and part of the ‘guard’ declaration (better context), and
definitely better than having a warning stay in your codebase.

Putting the code clarity aside, having a compiler error for a non-returned
guard seems like an overkill, and different that the other Swift
implementations (such as Switch that doesn’t need a break to not fall
through).

Xiaodi: Thank you for the links. Was an actual proposal ever formed for
this, or was it decided not to move forward?

Yarden

On June 20, 2016 at 1:33:54 AM, Adrian Zubarev via swift-evolution ( > swift-evolution@swift.org) wrote:

@implicitreturn guard a = b else { print(“foo”) }

Isn’t that just the same? I mean now you even write more boilerplate then
bebore.

How does your return type look, what are you trying to solve?

--
Adrian Zubarev
Sent with Airmail

Am 20. Juni 2016 um 08:30:39, Yarden Eitan via swift-evolution (
swift-evolution@swift.org) schrieb:

@implicitreturn guard a = b else { print(“foo”) }

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Yarden Eitan) #7

I agree that by having different implicit ending statements (i.e.
break/return/etc.) based on context makes it more complicated and less
intuitive. Having said that, I do think that an implicit ‘return’
with/without a warning (rather than an error), gives people the opportunity
to either exclude or include the ‘return’ statement if they wish. This give
the developers the optionality to choose what is the better code design
based on their personal preference (like one liner ‘if’s with or without
brackets). I do think that if there is a warning, it should also have the
option to be suppressed.

If you think the ‘return’ statement has to be stated, then why don’t we
enforce a ‘return’ statement at the end of void functions? ‘guard’ should
be treated and recognized in a way that ‘return’ is obvious, like void
function endings. I agree that because it is a new thing, it might take
time for people to see it as obviously as that.

Looking at the previous requests for this, it seems like it is a pain point
for several developers who see it redundant as most of their “guard”s use
the same “return” or “return nil” statement.

I think this current solution gives both ends the needed flexibility.

Yarden

···

On June 20, 2016 at 5:29:17 PM, Dany St-Amant (dsa.mls@icloud.com) wrote:

Le 20 juin 2016 à 02:30, Yarden Eitan via swift-evolution < swift-evolution@swift.org> a écrit :

...

My proposal is to allow for an implicit return when no ending statement is
provided. We could take this one step further and have the compiler aware
of it’s most inner scope and see if it is a while loop for example and
implicitly allow a break. But I think at least as a first step, by having
an implicit “return” we are saving the repetitiveness on many cases where
there are multiple guard statements and the return from them is obvious.

A 'guard' in a loop can commonly be used with either 'continue' or 'break',
the compiler would not be able to guess your intent. And whatever default
would be selected, it would be the wrong one for many scenarios.

The 'return' is an important keyword which, I think, should not be
obfuscated as one often need to quickly find all exit point of a function,
when debugging/analyzing code.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If you bring the consistency card, I would be more on the page of making
'break' mandatory and explicit in the 'switch'.

Dany

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).


(Xiaodi Wu) #8

I agree that by having different implicit ending statements (i.e.
break/return/etc.) based on context makes it more complicated and less
intuitive. Having said that, I do think that an implicit ‘return’
with/without a warning (rather than an error), gives people the opportunity
to either exclude or include the ‘return’ statement if they wish. This give
the developers the optionality to choose what is the better code design
based on their personal preference (like one liner ‘if’s with or without
brackets). I do think that if there is a warning, it should also have the
option to be suppressed.

Swift, by design, does not permit if statements without braces. It also, by
design, does not have optional warnings.

If you think the ‘return’ statement has to be stated, then why don’t we
enforce a ‘return’ statement at the end of void functions?

A `guard` statement is a control flow statement. It indicates that you are
prematurely exiting the scope, and therefore by design it requires you to
explain how you intend to do so.

···

On Mon, Jun 20, 2016 at 10:04 PM, Yarden Eitan via swift-evolution < swift-evolution@swift.org> wrote:

‘guard’ should be treated and recognized in a way that ‘return’ is
obvious, like void function endings. I agree that because it is a new
thing, it might take time for people to see it as obviously as that.

Looking at the previous requests for this, it seems like it is a pain
point for several developers who see it redundant as most of their “guard”s
use the same “return” or “return nil” statement.

I think this current solution gives both ends the needed flexibility.

Yarden

On June 20, 2016 at 5:29:17 PM, Dany St-Amant (dsa.mls@icloud.com) wrote:

Le 20 juin 2016 à 02:30, Yarden Eitan via swift-evolution < > swift-evolution@swift.org> a écrit :

...

My proposal is to allow for an implicit return when no ending statement is
provided. We could take this one step further and have the compiler aware
of it’s most inner scope and see if it is a while loop for example and
implicitly allow a break. But I think at least as a first step, by having
an implicit “return” we are saving the repetitiveness on many cases where
there are multiple guard statements and the return from them is obvious.

A 'guard' in a loop can commonly be used with either 'continue' or
'break', the compiler would not be able to guess your intent. And whatever
default would be selected, it would be the wrong one for many scenarios.

The 'return' is an important keyword which, I think, should not be
obfuscated as one often need to quickly find all exit point of a function,
when debugging/analyzing code.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If you bring the consistency card, I would be more on the page of making
'break' mandatory and explicit in the 'switch'.

Dany

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Yarden Eitan) #9

The one line ‘if’ was just a known example of having the capability to
choose based on preference, and is not the core of this issue.
If Swift doesn’t allow warnings to be suppressed, then what is
@discardableResult as an example.
I don’t find your last argument of it being a control flow statement as
persuasive.

I agree that by having different implicit ending statements (i.e.
break/return/etc.) based on context makes it more complicated and less
intuitive. Having said that, I do think that an implicit ‘return’
with/without a warning (rather than an error), gives people the opportunity
to either exclude or include the ‘return’ statement if they wish. This give
the developers the optionality to choose what is the better code design
based on their personal preference (like one liner ‘if’s with or without
brackets). I do think that if there is a warning, it should also have the
option to be suppressed.

Swift, by design, does not permit if statements without braces. It also, by
design, does not have optional warnings.

If you think the ‘return’ statement has to be stated, then why don’t we
enforce a ‘return’ statement at the end of void functions?

A `guard` statement is a control flow statement. It indicates that you are
prematurely exiting the scope, and therefore by design it requires you to
explain how you intend to do so.

···

On June 20, 2016 at 8:40:17 PM, Xiaodi Wu (xiaodi.wu@gmail.com) wrote:
On Mon, Jun 20, 2016 at 10:04 PM, Yarden Eitan via swift-evolution < swift-evolution@swift.org> wrote:

‘guard’ should be treated and recognized in a way that ‘return’ is
obvious, like void function endings. I agree that because it is a new
thing, it might take time for people to see it as obviously as that.

Looking at the previous requests for this, it seems like it is a pain
point for several developers who see it redundant as most of their “guard”s
use the same “return” or “return nil” statement.

I think this current solution gives both ends the needed flexibility.

Yarden

On June 20, 2016 at 5:29:17 PM, Dany St-Amant (dsa.mls@icloud.com) wrote:

Le 20 juin 2016 à 02:30, Yarden Eitan via swift-evolution < > swift-evolution@swift.org> a écrit :

...

My proposal is to allow for an implicit return when no ending statement is
provided. We could take this one step further and have the compiler aware
of it’s most inner scope and see if it is a while loop for example and
implicitly allow a break. But I think at least as a first step, by having
an implicit “return” we are saving the repetitiveness on many cases where
there are multiple guard statements and the return from them is obvious.

A 'guard' in a loop can commonly be used with either 'continue' or
'break', the compiler would not be able to guess your intent. And whatever
default would be selected, it would be the wrong one for many scenarios.

The 'return' is an important keyword which, I think, should not be
obfuscated as one often need to quickly find all exit point of a function,
when debugging/analyzing code.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If you bring the consistency card, I would be more on the page of making
'break' mandatory and explicit in the 'switch'.

Dany

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #10

I think I understand Yarden. I did some C# recently, which does not have *implicit* switch case fall-through and forces you to end all switch case bodies with break (for clarity I guess). It felt redundant coming from Swift. I understand why Adrian would feel the same way about void-return statements in guard. I don’t know, I’m a bit undecided on this issue. If we imagine this proposal, the fact that it only works on void-returning functions feels a bit weird.

···

On 20 Jun 2016, at 18:08, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

On the contrary, having a compiler error for a guard body that doesn't exit the scope is the very point of having guard.

The links were for your review because the discussion on this idea has been extensive and both times reached consensus that this is not a workable idea.

On Mon, Jun 20, 2016 at 09:12 Yarden Eitan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Adrian: I would prefer to not have it at all. But this is a better alternative than a brand new line declaring a return, and nothing else. This is inline and part of the ‘guard’ declaration (better context), and definitely better than having a warning stay in your codebase.

Putting the code clarity aside, having a compiler error for a non-returned guard seems like an overkill, and different that the other Swift implementations (such as Switch that doesn’t need a break to not fall through).

Xiaodi: Thank you for the links. Was an actual proposal ever formed for this, or was it decided not to move forward?

Yarden

On June 20, 2016 at 1:33:54 AM, Adrian Zubarev via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) wrote:

@implicitreturn guard a = b else { print(“foo”) }

Isn’t that just the same? I mean now you even write more boilerplate then bebore.

How does your return type look, what are you trying to solve?

--
Adrian Zubarev
Sent with Airmail

Am 20. Juni 2016 um 08:30:39, Yarden Eitan via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

@implicitreturn guard a = b else { print(“foo”) }

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

The one line ‘if’ was just a known example of having the capability to
choose based on preference, and is not the core of this issue.

My point is that, as an opinionated language, Swift rejects certain options
such as one-line `if` statements without braces. One consideration for
proposals is whether it fits with the direction of the language, and the
larger point here is that "having the capability to choose based on
preference" is not one of the aims of Swift.

From what I've gleaned from this list, a successful proposal nearly always

takes the form: "Currently, we have option A. However, A has the following
problems 1, 2, and 3. Here is option B, which solves these problems. Thus,
B is superior to A and I propose to replace A with B." I have seen very few
successful proposals (have there been any?) take the form: "Currently, we
have option A. However, some prefer B. Therefore, I propose that Swift
should have both A and B."

If Swift doesn’t allow warnings to be suppressed, then what is

@discardableResult as an example.

The annotation has semantic meaning, namely that the result is intended to
be discardable and the function can be called solely for its side effects.
It does not exist for the purpose of making warnings go away; rather, it is
what makes warnings about discarded results even possible.

Put another way, if Swift did not have that annotation, it is difficult to
imagine that it would produce warnings about discarded results at all. Note
how there is no compiler flag to suppress warnings about discarded results
specifically. Nor, by design, does there exist a compiler flag to suppress
any specific category of warnings.

I don’t find your last argument of it being a control flow statement as

persuasive.

The point is that `guard` being different from other statements is
deliberate. When you see `guard`, you know that control is being
transferred out of the scope before the closing brace. That is a feature,
not a bug. Without that feature, it'd just be a synonym for `if !(...)`.
There are many ways of transferring control out of the scope, including the
calling of any function annotated @noreturn. Therefore, you must write down
which one you choose.

···

On Mon, Jun 20, 2016 at 10:48 PM, Yarden Eitan <yarneo@gmail.com> wrote:

On June 20, 2016 at 8:40:17 PM, Xiaodi Wu (xiaodi.wu@gmail.com) wrote:

On Mon, Jun 20, 2016 at 10:04 PM, Yarden Eitan via swift-evolution < > swift-evolution@swift.org> wrote:

I agree that by having different implicit ending statements (i.e.
break/return/etc.) based on context makes it more complicated and less
intuitive. Having said that, I do think that an implicit ‘return’
with/without a warning (rather than an error), gives people the opportunity
to either exclude or include the ‘return’ statement if they wish. This give
the developers the optionality to choose what is the better code design
based on their personal preference (like one liner ‘if’s with or without
brackets). I do think that if there is a warning, it should also have the
option to be suppressed.

Swift, by design, does not permit if statements without braces. It also,
by design, does not have optional warnings.

If you think the ‘return’ statement has to be stated, then why don’t we
enforce a ‘return’ statement at the end of void functions?

A `guard` statement is a control flow statement. It indicates that you are
prematurely exiting the scope, and therefore by design it requires you to
explain how you intend to do so.

‘guard’ should be treated and recognized in a way that ‘return’ is
obvious, like void function endings. I agree that because it is a new
thing, it might take time for people to see it as obviously as that.

Looking at the previous requests for this, it seems like it is a pain
point for several developers who see it redundant as most of their “guard”s
use the same “return” or “return nil” statement.

I think this current solution gives both ends the needed flexibility.

Yarden

On June 20, 2016 at 5:29:17 PM, Dany St-Amant (dsa.mls@icloud.com) wrote:

Le 20 juin 2016 à 02:30, Yarden Eitan via swift-evolution < >> swift-evolution@swift.org> a écrit :

...

My proposal is to allow for an implicit return when no ending statement
is provided. We could take this one step further and have the compiler
aware of it’s most inner scope and see if it is a while loop for example
and implicitly allow a break. But I think at least as a first step, by
having an implicit “return” we are saving the repetitiveness on many cases
where there are multiple guard statements and the return from them is
obvious.

A 'guard' in a loop can commonly be used with either 'continue' or
'break', the compiler would not be able to guess your intent. And whatever
default would be selected, it would be the wrong one for many scenarios.

The 'return' is an important keyword which, I think, should not be
obfuscated as one often need to quickly find all exit point of a function,
when debugging/analyzing code.

This goes along the line of the Swift “switch” statement, which doesn’t
follow it’s predecessors and force a “break” but rather it is already
implicitly there.

If you bring the consistency card, I would be more on the page of making
'break' mandatory and explicit in the 'switch'.

Dany

If this proposal is too much of a leap, an alternative is to allow an
implicit return but provide a warning (not an error). This warning can be
suppressed using an @implicitreturn prefix to the guard statement or
something along those lines (@implicitreturn guard a = b else {
print(“foo”) } ).

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution