Guard Implicit Fallback


(Tighe Racicot) #1

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a
conversation concerning it.

For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return *void or nil* }"

What are your thoughts?

Tighe


Inferred return for guard statement
(Robert Widmann) #2

I agree the nil fallback case is a common one, but the loss of readability and decreased understanding of control flow here makes me think special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <swift-evolution@swift.org> のメッセージ:

···

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a conversation concerning it.

For example, I often have a function whose job depends on an optional having a value, and so I guard-let at the start and return if the guard fails. Or if the function returns an optional type, I'll simply return nil if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return void or nil }"

What are your thoughts?

Tighe

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


(Félix Cloutier) #3

Error cases are very often neglected and I feel that this would only encourage it.

Félix

···

Le 10 févr. 2016 à 22:40:48, Tighe Racicot via swift-evolution <swift-evolution@swift.org> a écrit :

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a conversation concerning it.

For example, I often have a function whose job depends on an optional having a value, and so I guard-let at the start and return if the guard fails. Or if the function returns an optional type, I'll simply return nil if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return void or nil }"

What are your thoughts?

Tighe

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


(Myles La Verne Schultz) #4

Generally, if you're using guard, you're looking for something that your program requires before moving on. If you get nil back, you probably want to do more than just return nil. When you're developing something, returning nil is simply convent, but doing something about that so the user realizes something has gone wrong is also important.

At the same time, I don't see why we couldn't have both: guard and guard else. Much like ARC, couldn't the compiler provide a case where lines that only specify guard automatically return nil and guards that specify an else run the specified else in that instance?

Myles

···

Sent from my iPhone

On Feb 10, 2016, at 10:40 PM, Tighe Racicot via swift-evolution <swift-evolution@swift.org> wrote:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a conversation concerning it.

For example, I often have a function whose job depends on an optional having a value, and so I guard-let at the start and return if the guard fails. Or if the function returns an optional type, I'll simply return nil if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return void or nil }"

What are your thoughts?

Tighe

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


(Alexey Demedetskiy) #5

Hey all

Can we align `guard` statement with `as` and `try` statements?

I mean enabling `guard?` and `guard!` versions.

guard! behavior is a pretty straightforward - raise an exception if condition is false.
In this case it will look like precondition(), but with conditional bindings.

guard? is a tricky one. What actually want to say - return default value.
in Void returning functions it is simple. It can be obvious in an Optional returning functions.
But this use cases are not general enough.

In other words, to give guard? statements enough semantics, we need to provide default return value
to function signature.

So, given small setup:

typealias UserID = Int
struct User { let id: UserID }

let users = [User(id: 1), User(id: 2)]

We can write findUser(byID:) function this way:

func findUser(byId id: UserID?) -> User? {
    guard let id = id else { return nil }

    for user in users {
        if user.id == id { return user }
    }
    
    return nil
}

And with guard? and function default return values this way:

func findUser(byId id: UserID?) -> User? = nil {
    guard? let id = id
    
    for user in users {
        if user.id == id { return user }
    }
}

Function default return values is an off topic here and can be moved to separate thread if anyone is interested.

Best regards,
Alexey Demedetskiy

···

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a conversation concerning it.

For example, I often have a function whose job depends on an optional having a value, and so I guard-let at the start and return if the guard fails. Or if the function returns an optional type, I'll simply return nil if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
guard let aValue = someOptional
....
}

and have that imply "else { returnvoid or nil}"

What are your thoughts?

Tighe


(Xiaodi Wu) #6

I believe this has already been proposed on the list in the past. I don't
have easy access to the archives at the moment so I can't provide a
convenient link.

The gist of it--or at least one of the compelling arguments against the
idea--was that the 'obvious' implicit behavior becomes non-obvious when you
take into account guard statements inside loops, for example. Do you
continue? break? return? And once you make a decision for each of the
scenarios envisioned you end up with a complicated series of fallbacks that
need extensive documentation, which is no longer much of a win over
explicitly writing your fallback.

···

On Thu, Feb 11, 2016 at 11:38 AM Developer via swift-evolution < swift-evolution@swift.org> wrote:

I agree the nil fallback case is a common one, but the loss of readability
and decreased understanding of control flow here makes me think
special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <
swift-evolution@swift.org> のメッセージ:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start
a conversation concerning it.

For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return *void or nil* }"

What are your thoughts?

Tighe

_______________________________________________
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


(Jonathan Tang) #7

I like the general elegance of aligning this with existing constructs, but
ultimately it would be of little use to me. Usually if a guard fails, I
want to log a message, or increment a counter, or at the very least have a
statement that I can stick a breakpoint on. This proposal is appealing to
me from a brevity POV, but I suspect that if it were adopted, a lot of
organizations would adopt code conventions that ban it so that you can more
easily follow the control flow when debugging.

···

On Thu, Feb 11, 2016 at 11:19 PM, Alexey Demedetskiy via swift-evolution < swift-evolution@swift.org> wrote:

Hey all

Can we align `guard` statement with `as` and `try` statements?

I mean enabling `guard?` and `guard!` versions.

guard! behavior is a pretty straightforward - raise an exception if
condition is false.
In this case it will look like precondition(), but with conditional
bindings.

guard? is a tricky one. What actually want to say - return default value.
in Void returning functions it is simple. It can be obvious in an Optional
returning functions.
But this use cases are not general enough.

In other words, to give guard? statements enough semantics, we need to
provide default return value
to function signature.

So, given small setup:

typealias UserID = Int
struct User { let id: UserID }

let users = [User(id: 1), User(id: 2)]

We can write findUser(byID:) function this way:

func findUser(byId id: UserID?) -> User? {
    guard let id = id else { return nil }

    for user in users {
        if user.id == id { return user }
    }

    return nil
}

And with guard? and function default return values this way:

func findUser(byId id: UserID?) -> User? = nil {
    guard? let id = id

    for user in users {
        if user.id == id { return user }
    }
}

Function default return values is an off topic here and can be moved to
separate thread if anyone is interested.

Best regards,
Alexey Demedetskiy

> Hey everyone,
>
> I feel that `guard` could be a little more Swifty and would like to
start a conversation concerning it.
>
> For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.
>
> Can we improve on the general fallback case? Could we simply say:
>
> func noReturn() {
> guard let aValue = someOptional
> ....
> }
>
> and have that imply "else { returnvoid or nil}"
>
> What are your thoughts?
>
> Tighe
>
>
>
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Kurt Werle) #8

It seems like this is related to the issue of closures and [weak self]. It
would be nice to have similar mechanisms for both.

func mustHaveAllParameters(arg: String!)*?* -> String? // only executes if
arg is not nil. Else returns nil/Void

object.withClosure() { [unowned self]*?* in ...} // only executes the
closure if self is not nil. Else returns nil/Void

···

On Thu, Feb 11, 2016 at 9:46 AM, Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

I believe this has already been proposed on the list in the past. I don't
have easy access to the archives at the moment so I can't provide a
convenient link.

The gist of it--or at least one of the compelling arguments against the
idea--was that the 'obvious' implicit behavior becomes non-obvious when you
take into account guard statements inside loops, for example. Do you
continue? break? return? And once you make a decision for each of the
scenarios envisioned you end up with a complicated series of fallbacks that
need extensive documentation, which is no longer much of a win over
explicitly writing your fallback.

On Thu, Feb 11, 2016 at 11:38 AM Developer via swift-evolution < > swift-evolution@swift.org> wrote:

I agree the nil fallback case is a common one, but the loss of
readability and decreased understanding of control flow here makes me think
special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <
swift-evolution@swift.org> のメッセージ:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start
a conversation concerning it.

For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return *void or nil* }"

What are your thoughts?

Tighe

_______________________________________________
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

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

--
kurt@CircleW.org
http://www.CircleW.org/kurt/


(Jessy) #9

The first related thought I had was answered by Chris Lattner:

https://forums.developer.apple.com/thread/4857

Does this proposal represent “code clarity”? Yes, I think so. Either guard must be paired with an “else”, or the else clause is the obvious, which is normally a return:

func ƒ<A, B, C>(a: A?, b: B?, c: C?) {
   guard let a = a, b = b, c = c else {return}
}

This is better:
guard let a, b, c

But what should it be in a loop? break? continue? I don’t think return would be appropriate. Not that I escape loops very often anymore; return is obvious for “forEach”, because it can’t “continue” or “break”.


(Thorsten Seitz) #10

+1 to the arguments of Robert and Xiaodi

-Thorsten

···

Am 11.02.2016 um 18:46 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

I believe this has already been proposed on the list in the past. I don't have easy access to the archives at the moment so I can't provide a convenient link.

The gist of it--or at least one of the compelling arguments against the idea--was that the 'obvious' implicit behavior becomes non-obvious when you take into account guard statements inside loops, for example. Do you continue? break? return? And once you make a decision for each of the scenarios envisioned you end up with a complicated series of fallbacks that need extensive documentation, which is no longer much of a win over explicitly writing your fallback.
On Thu, Feb 11, 2016 at 11:38 AM Developer via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I agree the nil fallback case is a common one, but the loss of readability and decreased understanding of control flow here makes me think special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start a conversation concerning it.

For example, I often have a function whose job depends on an optional having a value, and so I guard-let at the start and return if the guard fails. Or if the function returns an optional type, I'll simply return nil if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return void or nil }"

What are your thoughts?

Tighe

_______________________________________________
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


(ilya) #11

Agreed that explicit return is more readable.
I'd be happy to lose brackets around return though:

guard let value = optional else return

···

On Thu, Feb 11, 2016 at 18:46 Xiaodi Wu via swift-evolution < swift-evolution@swift.org> wrote:

I believe this has already been proposed on the list in the past. I don't
have easy access to the archives at the moment so I can't provide a
convenient link.

The gist of it--or at least one of the compelling arguments against the
idea--was that the 'obvious' implicit behavior becomes non-obvious when you
take into account guard statements inside loops, for example. Do you
continue? break? return? And once you make a decision for each of the
scenarios envisioned you end up with a complicated series of fallbacks that
need extensive documentation, which is no longer much of a win over
explicitly writing your fallback.
On Thu, Feb 11, 2016 at 11:38 AM Developer via swift-evolution < > swift-evolution@swift.org> wrote:

I agree the nil fallback case is a common one, but the loss of
readability and decreased understanding of control flow here makes me think
special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <
swift-evolution@swift.org> のメッセージ:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to start
a conversation concerning it.

For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return *void or nil* }"

What are your thoughts?

Tighe

_______________________________________________
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

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


(Ilya Belenkiy) #12

Losing brackets around the return would mean that no additional statements
(for example logging or some other useful thing) will be possible in the
early return

···

On Fri, Feb 12, 2016 at 2:26 AM ilya via swift-evolution < swift-evolution@swift.org> wrote:

Agreed that explicit return is more readable.
I'd be happy to lose brackets around return though:

guard let value = optional else return

On Thu, Feb 11, 2016 at 18:46 Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

I believe this has already been proposed on the list in the past. I don't
have easy access to the archives at the moment so I can't provide a
convenient link.

The gist of it--or at least one of the compelling arguments against the
idea--was that the 'obvious' implicit behavior becomes non-obvious when you
take into account guard statements inside loops, for example. Do you
continue? break? return? And once you make a decision for each of the
scenarios envisioned you end up with a complicated series of fallbacks that
need extensive documentation, which is no longer much of a win over
explicitly writing your fallback.
On Thu, Feb 11, 2016 at 11:38 AM Developer via swift-evolution < >> swift-evolution@swift.org> wrote:

I agree the nil fallback case is a common one, but the loss of
readability and decreased understanding of control flow here makes me think
special-casing this isn't all it's cracked up to be.

~Robert Widmann

2016/02/10 22:40、Tighe Racicot via swift-evolution <
swift-evolution@swift.org> のメッセージ:

Hey everyone,

I feel that `guard` could be a little more Swifty and would like to
start a conversation concerning it.

For example, I often have a function whose job depends on an optional
having a value, and so I guard-let at the start and return if the guard
fails. Or if the function returns an optional type, I'll simply return nil
if guard fails.

Can we improve on the general fallback case? Could we simply say:

func noReturn() {
    guard let aValue = someOptional
    ....
}

and have that imply "else { return *void or nil* }"

What are your thoughts?

Tighe

_______________________________________________
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

_______________________________________________
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