guard let x = x


(David Goodine) #1

Hey all,

As usual, apologies if this horse was beaten ages ago before I joined the mailing list, but thought I would bring this up.

I was typing the above (for the hundredth time) the other day and I was wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

I was never convinced why implicit nil checks (i.e. if x {…}) were such a bad thing. But now in Swift it seems that it would be much more convenient to be able to simply skip the assignment part of the expression and define the above as guaranteeing and unwrapping x, y and z in the appropriate scope.

I think with such powerful and already compact expressions now wanting to get on the same line,adding this would make the language even more compact and elegant. It could be added as a non-source-breaking change, still allowing x = x for those who prefer it, but could significantly tighten up such uses, which I’m finding are ubiquitous in my code.

Any thoughts?

-d


(Erica Sadun) #2

There are safety arguments to be made for introducing a way to bind an optional to a shadowed variable that is guaranteed to be the same name ensuring the conditionally bound item does not accidentally shadow any other item.

Your initial suggestion doesn't work as overloading "let" confuses rather than clarifies this process. In February, I brought up `bind x` to mean "conditionally bind x to x, and produce a conditional fail if that's not possible", with the hope that "bind self" could be used in closures. Under that scheme your example would read:

guard bind x, bind y, bind z else { ... }

"The bind thread" was discussed during the first week of February 2016. Joe Groff had said: "If you all are serious about this, I think you should start a new thread about it." I thought it was worth a serious discussion just so it could be evaluated and either adopted or discarded and dropped forever. The arguments for:

* Simplifying an mildly complex and potentially misleading statement
* Creating a deliberate and controlled rather than accidental shadowing style

The discussion petered out, with Kevin Ballard making the strongest case against: "If your goal here is to just avoid having to write the `= foo`, then I disagree with the whole motive. If your goal here is to just use a keyword `bind` instead of `let` (e.g. if you want to use `if bind foo = foo { ... }`), I still disagree, because this new keyword serves no purpose. `if let foo = bar { ... }` is not "fundamentally different" than `let foo = bar`, it's still binding a new identifier to a value, the only difference is it binds it to an optional value. And it's really just a specialization of `if case let foo? = bar { ... }`. I've asked in the past about whether it's worth keeping the special case around now that we have `if case let` (or more specifically, if we should just turn `if let` into the generalized version, so you'd say `if let foo? = bar {... }`) and the answer from the core team was that they already tried it internally and found that the usage of optionals was so prevalent that the special-case optional-specific form of `if let` was worth keeping."

There was not sufficient support to push forward with this, and reasonable arguments against. I'd suggest the long since beaten horse has moved on to a better world.

-- E

···

On Oct 26, 2016, at 5:40 AM, David Goodine via swift-evolution <swift-evolution@swift.org> wrote:

Hey all,

As usual, apologies if this horse was beaten ages ago before I joined the mailing list, but thought I would bring this up.

I was typing the above (for the hundredth time) the other day and I was wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

I was never convinced why implicit nil checks (i.e. if x {…}) were such a bad thing. But now in Swift it seems that it would be much more convenient to be able to simply skip the assignment part of the expression and define the above as guaranteeing and unwrapping x, y and z in the appropriate scope.

I think with such powerful and already compact expressions now wanting to get on the same line,adding this would make the language even more compact and elegant. It could be added as a non-source-breaking change, still allowing x = x for those who prefer it, but could significantly tighten up such uses, which I’m finding are ubiquitous in my code.

Any thoughts?

-d


(Pyry Jahkola) #3

Going back to the originating message of this thread. This idea (or a variant thereof) has been mentioned in the list of Commonly Rejected Proposals (2nd last bullet under Control Flow, Closures, Optional Binding, and Error Handling <https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md#control-flow-closures-optional-binding-and-error-handling>):

Syntactic sugar for if let self-assignment <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026796.html>: An alternative syntax (such as if let foo? { ... } or if let foo=? { ... }) to serve as a shorthand for if let foo = foo { ... } is often proposed and rejected because it is favoring terseness over clarity by introducing new magic syntactic sugar.

So any discussion on this topic would have to target these concerns first.

···

On 26 Oct 2016, David Goodine wrote:

I was typing the above (for the hundredth time) the other day and I was wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

That said, while I don't mind having to repeat the variable name myself, I think David Goodine's syntax would have to repeat the `let` to align with SE-0099 <https://github.com/apple/swift-evolution/blob/master/proposals/0099-conditionclauses.md>, like so:

    guard let x, let y, let z else { ... }

Personally, I wouldn't mind if this syntax existed. I think it explains itself rather well. And today, unlike when it was first discussed a long time before SE-0099, it's no longer confusable with Boolean conditions.

But it's certainly out of scope for Swift 4 phase 1.

— Pyry


(David Sweeris) #4

Between all the talk about unwrap and nonnill and whatnot, I've kinda lost track of what we're actually talking about. I think it's still about not having to type variables twice in guard statements, right? Has anyone suggested
    guard x! else {...}
    // x means x! now
yet?

- Dave Sweeris


(Chris Lattner) #5

Hey all,

As usual, apologies if this horse was beaten ages ago before I joined the mailing list, but thought I would bring this up.

Yes, this has thoroughly been beaten to death. It is also outside the scope of Swift 4 stage 1. That said, it is such a glaring problem that we’ll have to deal with it at some point.

I was typing the above (for the hundredth time) the other day and I was wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

This specific syntax is commonly requested. The problem with this is that it provides no useful information about what is actually going on: it sacrifices clarity to get terseness, a specific non-goal of Swift.

Erica says:

Your initial suggestion doesn't work as overloading "let" confuses rather than clarifies this process. In February, I brought up `bind x` to mean "conditionally bind x to x, and produce a conditional fail if that's not possible", with the hope that "bind self" could be used in closures. Under that scheme your example would read:

guard bind x, bind y, bind z else { … }

To me, this is the most promising direction, but I’d suggest the use of “unwrap" as the keyword. If you compare these two:

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I think that b) wins by virtue of eliminating repetition ("foobar = foobar" fails DRY principles), but retains clarity by introducing a word into the grammar that people already commonly know and use, and which is googlable if they don’t.

This also gives us the conceptual hook to make the “unwrapping an optional” behavior (which occurs with if let, optional chaining, etc) be something that could be extended to other similar user defined types, such as a Result type.

-Chris

···

On Oct 26, 2016, at 8:58 AM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 26, 2016, at 5:40 AM, David Goodine via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


(Josh Parmenter) #6

To me, this is the most promising direction, but I’d suggest the use of “unwrap" as the keyword. If you compare these two:

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I think that b) wins by virtue of eliminating repetition ("foobar = foobar" fails DRY principles), but retains clarity by introducing a word into the grammar that people already commonly know and use, and which is googlable if they don’t.

I find b) to be quite convincing.

Best,

Josh

Joshua Parmenter | Engineering Lead, Apple Technologies

T 248 777 7777
C 206 437 1551
F 248 616 1980
www.vectorform.com<http://www.vectorform.com/>

Vectorform
2107 Elliott Ave Suite 303
Seattle, WA 98121 USA

Think Tank. Lab. Studio.
We invent digital products and experiences.

SEATTLE | DETROIT | NEW YORK | MUNICH | HYDERABAD

···

On Oct 26, 2016, at 9:37 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:


(David Goodine) #7

First off, Chris made it clear dealing with this isn't a priority for Swift 4 so take my comments (inline below) with a grain of salt. At least for the time being this horse should Rest In Peace.

Hey all,

As usual, apologies if this horse was beaten ages ago before I joined the mailing list, but thought I would bring this up.

I was typing the above (for the hundredth time) the other day and I was wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

I was never convinced why implicit nil checks (i.e. if x {…}) were such a bad thing. But now in Swift it seems that it would be much more convenient to be able to simply skip the assignment part of the expression and define the above as guaranteeing and unwrapping x, y and z in the appropriate scope.

I think with such powerful and already compact expressions now wanting to get on the same line,adding this would make the language even more compact and elegant. It could be added as a non-source-breaking change, still allowing x = x for those who prefer it, but could significantly tighten up such uses, which I’m finding are ubiquitous in my code.

Any thoughts?

-d

There are safety arguments to be made for introducing a way to bind an optional to a shadowed variable that is guaranteed to be the same name ensuring the conditionally bound item does not accidentally shadow any other item.

Chris also raised this in a comment in this thread, and I agree with Swift's philosophy that terseness shouldn't compromise clarity of intent.

What I don't get is why 'let x = x' is any clearer than the alternative I suggested. It's intent is only clear because the language defines it as such. In fact, I would argue that to programmers familiar with most other popular languages, it's intuitively unclear, even meaningless (except for being a rare reference to a 1980s Laurie Anderson song).

I was simply suggesting that since neither is a familiar syntax, Swift could simple "define it as such" in a more compact (and as Chris pointed out, more DRY form).

That said, I do like your earlier proposal to introduce the 'bind' form (and agree with Chris that 'unwrap' would be clearer). Perhaps that's the way to go when it's time to tackle the issue.

-d

(p.s. I'm still secretly trying to work a reference to the Dead Parrot sketch to issues like these. Perhaps one day...)

···

On Oct 26, 2016, at 11:58 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Oct 26, 2016, at 5:40 AM, David Goodine via swift-evolution <swift-evolution@swift.org> wrote:

Your initial suggestion doesn't work as overloading "let" confuses rather than clarifies this process. In February, I brought up `bind x` to mean "conditionally bind x to x, and produce a conditional fail if that's not possible", with the hope that "bind self" could be used in closures. Under that scheme your example would read:

guard bind x, bind y, bind z else { ... }

"The bind thread" was discussed during the first week of February 2016. Joe Groff had said: "If you all are serious about this, I think you should start a new thread about it." I thought it was worth a serious discussion just so it could be evaluated and either adopted or discarded and dropped forever. The arguments for:

* Simplifying an mildly complex and potentially misleading statement
* Creating a deliberate and controlled rather than accidental shadowing style

The discussion petered out, with Kevin Ballard making the strongest case against: "If your goal here is to just avoid having to write the `= foo`, then I disagree with the whole motive. If your goal here is to just use a keyword `bind` instead of `let` (e.g. if you want to use `if bind foo = foo { ... }`), I still disagree, because this new keyword serves no purpose. `if let foo = bar { ... }` is not "fundamentally different" than `let foo = bar`, it's still binding a new identifier to a value, the only difference is it binds it to an optional value. And it's really just a specialization of `if case let foo? = bar { ... }`. I've asked in the past about whether it's worth keeping the special case around now that we have `if case let` (or more specifically, if we should just turn `if let` into the generalized version, so you'd say `if let foo? = bar {... }`) and the answer from the core team was that they already tried it internally and found that the usage of optionals was so prevalent that the special-case optional-specific form of `if let` was worth keeping."

There was not sufficient support to push forward with this, and reasonable arguments against. I'd suggest the long since beaten horse has moved on to a better world.

-- E


(David Waite) #8

I know that there has been many conversations about a cleaner syntax for conditional unwrapping of optionals on this list. My concern in the past has been whether this makes it confusing for new developers to understand whether “foobar” is a shadowed variable within the block (or for guard, after the block) or if it is an alias.

-DW

···

On Oct 26, 2016, at 9:37 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

To me, this is the most promising direction, but I’d suggest the use of “unwrap" as the keyword. If you compare these two:

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I think that b) wins by virtue of eliminating repetition ("foobar = foobar" fails DRY principles), but retains clarity by introducing a word into the grammar that people already commonly know and use, and which is googlable if they don’t.

This also gives us the conceptual hook to make the “unwrapping an optional” behavior (which occurs with if let, optional chaining, etc) be something that could be extended to other similar user defined types, such as a Result type.


(David Waite) #9

To me, this is the most promising direction, but I’d suggest the use of “unwrap" as the keyword. If you compare these two:

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I think that b) wins by virtue of eliminating repetition ("foobar = foobar" fails DRY principles), but retains clarity by introducing a word into the grammar that people already commonly know and use, and which is googlable if they don’t.

This also gives us the conceptual hook to make the “unwrapping an optional” behavior (which occurs with if let, optional chaining, etc) be something that could be extended to other similar user defined types, such as a Result type.

This might need a bit more fleshing out of the details. Given a result of T or Error, I would expect the unwrap operation’s flow control to not be a conditional but a throw - aka "try unwrap result” (or no need for a keyword - try result.unwrap()). That is, unless I specifically request a projection.

For an async/await system based on promises, I would expect to use an “await” keyword, not an “unwrap” keyword.

···

On Oct 26, 2016, at 10:37 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

-Chris

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


(Erica Sadun) #10

I'd be against this alternative as it is doing the work of a guard statement (including the "must exit scope" rule) with a new keyword and unneeded redundancy.

Adding "unwrap" is local. It performs one very common task with added safety (avoids unintended shadow effects) and introduces succinctness and clarity. In other words, it is a highly focused changed with a measurable benefit in use.

Compare:

* "Introduce the unwrap statement that acts like guard but is limited to optionals" creates unnecessary language verbosity.

* "guard x else ", meaning "treat optional values differently than all other items in a conditional list", fails because it obscures rather than adds intent. Worse, it would lead to issues with Boolean optionals whose wrapped value is later used within the same condition.

Xiaodi, you mentioned an alternative approach and I'd love a peek at what that is.

-- Erica

···

On Oct 31, 2016, at 1:51 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

An alternative that would seem to satisfy some objections is to have a distinct "unwrap" statement--as in: "unwrap x else { ... }".


(William Sumner) #11

Your proposed form of unwrap naturally works in multiple places with clear readability:

var foo: Any?
if unwrap foo {}

while unwrap foo {}

guard unwrap foo else { return }

Preston

···

On Oct 31, 2016, at 3:44 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 31, 2016, at 1:51 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

An alternative that would seem to satisfy some objections is to have a distinct "unwrap" statement--as in: "unwrap x else { ... }".

I'd be against this alternative as it is doing the work of a guard statement (including the "must exit scope" rule) with a new keyword and unneeded redundancy.

Adding "unwrap" is local. It performs one very common task with added safety (avoids unintended shadow effects) and introduces succinctness and clarity. In other words, it is a highly focused changed with a measurable benefit in use.

Compare:

* "Introduce the unwrap statement that acts like guard but is limited to optionals" creates unnecessary language verbosity.

* "guard x else ", meaning "treat optional values differently than all other items in a conditional list", fails because it obscures rather than adds intent. Worse, it would lead to issues with Boolean optionals whose wrapped value is later used within the same condition.

Xiaodi, you mentioned an alternative approach and I'd love a peek at what that is.

— Erica


(Xiaodi Wu) #12

>
> An alternative that would seem to satisfy some objections is to have a
distinct "unwrap" statement--as in: "unwrap x else { ... }".

I'd be against this alternative as it is doing the work of a guard
statement (including the "must exit scope" rule) with a new keyword and
unneeded redundancy.

Adding "unwrap" is local. It performs one very common task with added
safety (avoids unintended shadow effects) and introduces succinctness and
clarity. In other words, it is a highly focused changed with a measurable
benefit in use.

Sure, I have no beef with `guard unwrap`. My point was that, if there's a
push for a more succinct statement, it must be `unwrap x` and not `guard x`
or `guard let x` for the same reasons we've discussed above.

Compare:

* "Introduce the unwrap statement that acts like guard but is limited to
optionals" creates unnecessary language verbosity.

* "guard x else ", meaning "treat optional values differently than all
other items in a conditional list", fails because it obscures rather than
adds intent. Worse, it would lead to issues with Boolean optionals whose
wrapped value is later used within the same condition.

Xiaodi, you mentioned an alternative approach and I'd love a peek at what
that is.

Not for unwrapping; for enums. I'll write you offlist :slight_smile:

···

On Mon, Oct 31, 2016 at 4:44 PM, Erica Sadun <erica@ericasadun.com> wrote:

> On Oct 31, 2016, at 1:51 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

-- Erica


(Greg Parker) #13

And perhaps plain old:

unwrap! foo
// i.e. guard unwrap foo else { crash }

···

On Oct 31, 2016, at 3:46 PM, William Sumner via swift-evolution <swift-evolution@swift.org> wrote:

Your proposed form of unwrap naturally works in multiple places with clear readability:

var foo: Any?
if unwrap foo {}

while unwrap foo {}

guard unwrap foo else { return }

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler


(David Goodine) #14

One thing I really like that Erica mentioned in the earlier discussion is the case of guard unwrapping [weak self] in closures. I've taken to creating an alternate self (guard let ss = self else { return }) constant and using that. But it always felt inelegant. The proposed case works without falling prey to the protection against redefining self that the compiler still needs to enforce and does it in a way that's clear and concise.

···

Sent from my iPhone

On Oct 31, 2016, at 6:46 PM, William Sumner via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 31, 2016, at 3:44 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Oct 31, 2016, at 1:51 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

An alternative that would seem to satisfy some objections is to have a distinct "unwrap" statement--as in: "unwrap x else { ... }".

I'd be against this alternative as it is doing the work of a guard statement (including the "must exit scope" rule) with a new keyword and unneeded redundancy.

Adding "unwrap" is local. It performs one very common task with added safety (avoids unintended shadow effects) and introduces succinctness and clarity. In other words, it is a highly focused changed with a measurable benefit in use.

Compare:

* "Introduce the unwrap statement that acts like guard but is limited to optionals" creates unnecessary language verbosity.

* "guard x else ", meaning "treat optional values differently than all other items in a conditional list", fails because it obscures rather than adds intent. Worse, it would lead to issues with Boolean optionals whose wrapped value is later used within the same condition.

Xiaodi, you mentioned an alternative approach and I'd love a peek at what that is.

— Erica

Your proposed form of unwrap naturally works in multiple places with clear readability:

var foo: Any?
if unwrap foo {}

while unwrap foo {}

guard unwrap foo else { return }

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


(Xiaodi Wu) #15

An alternative that would seem to satisfy some objections is to have a
distinct "unwrap" statement--as in: "unwrap x else { ... }".

···

On Mon, Oct 31, 2016 at 14:49 Pyry Jahkola via swift-evolution < swift-evolution@swift.org> wrote:

Going back to the originating message of this thread. This idea (or a
variant thereof) has been mentioned in the list of Commonly Rejected
Proposals (2nd last bullet under Control Flow, Closures, Optional
Binding, and Error Handling
<https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md#control-flow-closures-optional-binding-and-error-handling>
):

Syntactic sugar for if let self-assignment
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160829/026796.html>:
An alternative syntax (such as if let foo? { ... } or if let foo=? { ... })
to serve as a shorthand for if let foo = foo { ... } is often proposed and
rejected because it is favoring terseness over clarity by introducing new
magic syntactic sugar.

So any discussion on this topic would have to target these concerns first.

On 26 Oct 2016, David Goodine wrote:

I was typing the above (for the hundredth time) the other day and I was
wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

That said, while I don't mind having to repeat the variable name myself, I
think David Goodine's syntax would have to repeat the `let` to align with
SE-0099
<https://github.com/apple/swift-evolution/blob/master/proposals/0099-conditionclauses.md>,
like so:

    *guard let* x, *let* y, *let* z *else* { ... }

Personally, I wouldn't mind if this syntax existed. I think it explains
itself rather well. And today, unlike when it was first discussed a long
time before SE-0099, it's no longer confusable with Boolean conditions.

But it's certainly out of scope for Swift 4 phase 1.

— Pyry

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


(Pyry Jahkola) #16

True. The `let`, on the other hand, has the minor upside that it's naturally substituted with `var` where in-place mutation is needed:

    guard let value, var collection else { ... }
    collection.append(value)
    // ...

Disclaimer: I don't know if this is a realistic usage scenario but it seems more natural to Swift, in my view.

— Pyry

···

On 31 Oct 2016, Xiaodi Wu wrote:

An alternative that would seem to satisfy some objections is to have a distinct "unwrap" statement--as in: "unwrap x else { ... }".


(Charlie Monroe) #17

Isn't this ambiguous in case x is Bool? (Optional<Bool>)? Do you mean to force-unwrap the bool and use it as a condition, or should the x be unwrapped (in which case it can be false)?

Not a common case likely, but it is nevertheless something to think of.

···

On Nov 1, 2016, at 6:52 AM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

Between all the talk about unwrap and nonnill and whatnot, I've kinda lost track of what we're actually talking about. I think it's still about not having to type variables twice in guard statements, right? Has anyone suggested
   guard x! else {...}
   // x means x! now
yet?

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


#18

Also with the 'guard unwrap', the following code make sense:

guard unwrap x, x == 10 else { return }

With a lone unwrap it would not.

unwrap x, x == 10 else { return }

I personally do not like shadowing, but a standalone 'unwrap!' could be of interest to those loving life in the shadows. Beside the shadowing itself, it should not be any worst than any of the other '!' usage. The feasibility of such depends of course on how the compiler manages its variable scoping.

On further thought, if we were to make the, sorry bad word coming, code-breaking change to disallow legacy shadowing 'let x=x' and force the shadowing to be done exclusively via this 'unwrap' keyword, it could make it easier for projects/companies to ban shadowing.

Dany

···

Le 31 oct. 2016 à 17:44, Erica Sadun via swift-evolution <swift-evolution@swift.org> a écrit :

On Oct 31, 2016, at 1:51 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

An alternative that would seem to satisfy some objections is to have a distinct "unwrap" statement--as in: "unwrap x else { ... }".

I'd be against this alternative as it is doing the work of a guard statement (including the "must exit scope" rule) with a new keyword and unneeded redundancy.

Adding "unwrap" is local. It performs one very common task with added safety (avoids unintended shadow effects) and introduces succinctness and clarity. In other words, it is a highly focused changed with a measurable benefit in use.

Compare:

* "Introduce the unwrap statement that acts like guard but is limited to optionals" creates unnecessary language verbosity.

* "guard x else ", meaning "treat optional values differently than all other items in a conditional list", fails because it obscures rather than adds intent. Worse, it would lead to issues with Boolean optionals whose wrapped value is later used within the same condition.

Xiaodi, you mentioned an alternative approach and I'd love a peek at what that is.


(ilya) #19

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I would argue for
c) guard let reallyFoobar = foobar else { … }

(or perhaps guard let foobar_ = foobar else { … } )

That way one can use both an optional foobar and non-optional "unwrapped
value of foobar at the moment of guard" without any possibility of mixing
those two (and without violating DRY).

Ilya.

···

On Wed, Oct 26, 2016 at 6:38 PM Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

On Oct 26, 2016, at 8:58 AM, Erica Sadun via swift-evolution < > swift-evolution@swift.org> wrote:

On Oct 26, 2016, at 5:40 AM, David Goodine via swift-evolution < > swift-evolution@swift.org> wrote:

Hey all,

As usual, apologies if this horse was beaten ages ago before I joined the
mailing list, but thought I would bring this up.

Yes, this has thoroughly been beaten to death. It is also outside the
scope of Swift 4 stage 1. That said, it is such a glaring problem that
we’ll have to deal with it at some point.

I was typing the above (for the hundredth time) the other day and I was
wondering whether it might be worth considering offering a shorter syntax:

guard let x, y, z else {…}

This specific syntax is commonly requested. The problem with this is that
it provides no useful information about what is actually going on: it
sacrifices clarity to get terseness, a specific non-goal of Swift.

Erica says:

Your initial suggestion doesn't work as overloading "let" confuses rather
than clarifies this process. In February, I brought up `bind x` to mean
"conditionally bind x to x, and produce a conditional fail if that's not
possible", with the hope that "bind self" could be used in closures. Under
that scheme your example would read:

guard bind x, bind y, bind z else { … }

To me, this is the most promising direction, but I’d suggest the use of
“unwrap" as the keyword. If you compare these two:

a) guard let foobar = foobar else { … }
b) guard unwrap foobar else { … }

I think that b) wins by virtue of eliminating repetition ("foobar =
foobar" fails DRY principles), but retains clarity by introducing a word
into the grammar that people already commonly know and use, and which is
googlable if they don’t.

This also gives us the conceptual hook to make the “unwrapping an
optional” behavior (which occurs with if let, optional chaining, etc) be
something that could be extended to other similar user defined types, such
as a Result type.

-Chris

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


(Chris Lattner) #20

It wouldn’t: “unwrap” would never include an equal sign. If you want to do that, use a standard "if let”.

-Chris

···

On Oct 26, 2016, at 10:23 AM, Joshua Alvarado <alvaradojoshua0@gmail.com> wrote:

In your example the keyword only makes sense if you are shadowing the optional variable. How would unwrap work with a different name?