[swift-evolution] More flexible guard statement

Adrian Kashivskyy adrian.kashivskyy at me.com
Wed Dec 16 02:49:43 CST 2015


Arthur,

> There’s a parallel thread going on right now about adding unless/until into the stdlib. I think that’s what you may want.

`guard` cannot be compared to `if` or `unless` because it's used as an assertion with an early exit, not a condition. Consider the following:

> let x: Int? = 5
> 
> guard let x = x where 1...10 ~= x else {
> 	return
> }
> 
> // x is unwrapped and between 1 and 10
> print(x)

Compare this to `unless`:

> unless let x = x where 1...10 ~= x {
> 	// x is unwrapped and between 1 and 10
> 	print(x)
> } else {
> 	return
> }

As you can see, `unless` introduces two new scopes and leads to creation of an indentation, which can result in a pyramid of doom. In addition, `guard` requires you to early exit the scope using `return` or `break`, which is not the case when using `unless`.

That being said, I don't fully understand the original problem, because this is possible:

> guard
> 	let col = tableView?.columnWithIdentifier("MyColumn"),
> 	let headerCell = tableView?.tableColumns[0].headerCell as? MyTableHeaderCell
> 	where col != -1
> else {
> 	NSBeep()
> 	print("an error occurred")
> 	return
> }


Pozdrawiam – Regards,
Adrian Kashivskyy

> Wiadomość napisana przez Jeff Kelley via swift-evolution <swift-evolution at swift.org> w dniu 14.12.2015, o godz. 03:45:
> 
> The first line of your example would need to use self.tableView, which is optional, so col would be optional as well. The assignment happens after the unwrap.
> 
> I find this a lot in my code where I need to chain together a string of optional unwrapping and assignment from those optionals, like so:
> 
>> if let foo = foo, bar = foo.bar, baz =foo.baz {
>> 
>> }
> 
> In that case, if bar is a non-optional property of foo, I need to rewrite it like this:
> 
>> if let foo = foo, baz = foo.baz {
>> 	let bar = foo.bar
>> 
>> }
> 
> These examples aren’t too bad, but as you add more layers of unwrapping, it gets more difficult to do without multiple levels of indentation—though this is probably more a code smell than anything else.
> 
> 
> Jeff Kelley
> 
> SlaunchaMan at gmail.com <mailto:SlaunchaMan at gmail.com> | @SlaunchaMan <https://twitter.com/SlaunchaMan> | jeffkelley.org <http://jeffkelley.org/>
>> On Dec 12, 2015, at 3:58 PM, Zef Houssney via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Jacob, you actually don’t need to have the redundant guard statement. If you want to assign something to a constant or variable, you just do that before the `guard let`, and you can still use it in the `where`:
>> 
>> let col = tableView.columnWithIdentifier("MyColumn")
>> guard let tableView = self.tableView where col != -1 else {
>>  NSBeep()
>>  print("an error occurred")
>>  return
>> }
>> 
>> Zef
>> 
>> 
>> 
>>> On Dec 12, 2015, at 11:23 AM, Al Skipp via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> How about extending ‘NSTableView’ with a subscript?
>>> 
>>> extension NSTableView {
>>> subscript(columnID columnID: String) -> Int? {
>>>   get {
>>>     let c = columnWithIdentifier(columnID)
>>>     return c >= 0 ? c : .None
>>>   }
>>> }
>>> }
>>> 
>>> tableView[columnID: "MyColumn"]
>>> 
>>> 
>>> It doesn’t address the general case, but it does introduce a more Swifty way of dealing with non-existent return values in this use case and would enable you to use it with guard.
>>> 
>>> Al
>>> 
>>>> On 12 Dec 2015, at 17:43, Jakob Egger via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>> At the moment "guard let" can only be used for unwrapping optionals. It
>>>> would be really nice if it could also be used with non-optional values.
>>>> For example, I'd like to write code like the following
>>>> 
>>>> guard 
>>>>  let tableView = self.tableView,
>>>>  let col = tableView.columnWithIdentifier("MyColumn") where col != -1
>>>> else {
>>>>  NSBeep()
>>>>  print("an error occurred")
>>>>  return
>>>> }
>>>> 
>>>> This is not possible, because the second let assignment is non-optional,
>>>> so I have to write it like this:
>>>> 
>>>> guard let tableView = self.tableView else {
>>>>  NSBeep()
>>>>  print("an error occurred")
>>>>  return
>>>> }
>>>> let col = tableView.columnWithIdentifier("MyColumn")
>>>> guard col != -1 else {
>>>>  NSBeep()
>>>>  print("an error occurred")
>>>>  return
>>>> }
>>>> 
>>>> This leads to a lot of duplicated error handling code.
>>>> 
>>>> Ideally, I'd also like to mix let & where clauses in a single guard
>>>> statement, like this:
>>>> 
>>>> guard 
>>>>  let tableView = self.tableView,
>>>>  let col = tableView.columnWithIdentifier("MyColumn") where col !=
>>>>  -1,
>>>>  let headerCell = tableView.tableColumns[col].headerCell as?
>>>>  MyTableHeaderCell
>>>> else {
>>>>  NSBeep()
>>>>  print("an error occurred")
>>>>  return
>>>> }
>>>> 
>>>> What do you think? Right now I always end up writing a lot of separate
>>>> guard statement, and I have a lot of repeated error handling code.
>>>> 
>>>> 
>>>> Best regards,
>>>> Jakob
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151216/eb43c8f3/attachment-0001.html>


More information about the swift-evolution mailing list