[swift-evolution] Proposal: Add implicit/default else-behaviour for the guard statement

Erica Sadun erica at ericasadun.com
Wed Dec 16 18:30:55 CST 2015


Count me in as a "no". Despite the redundancy, actually spelling out how the else clause leaves scope is valuable to reading the code.

-- E



> On Dec 16, 2015, at 4:40 PM, Radosław Pietruszewski via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I’m also against, for two reasons:
> 
> - looking at my code, `return` and `return nil` are most common, but not super-overwhelmingly so. I’m all for common-sense default behavior, but here, I’m just not convinced it’s worth it. Likewise, I hate noise in code, but I’m not bothered by explicit `else` blocks at all.
> - guard is already confusing enough until you truly, fully get it. Having an `else` block makes it far more clearer that it’s a (specialized) branching operation. Having something implicitly return from my method sounds almost scary.
> 
> — Radek
> 
>> On 17 Dec 2015, at 00:26, Stephen Celis via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> I'm opposed. I don't think `else { return }` is enough of a mouthful to add a default behavior that must be learned and reasoned with.
>> 
>> Stephen
>> 
>> On Wed, Dec 16, 2015 at 5:36 PM, Vester Gottfried via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> I just skipped through 200+ guard statements that return Void, nil or a value and no statement was inside a scope that can be exited with break. 
>> 
>> I am also thinking about the proposals regarding default values to return, but I am not sure if this would even be necessary.  In my case 80% of all guard statements end with "else { return }" or "else { return nil }". 
>> 
>> On Wed, Dec 16, 2015 at 11:20 PM, Etan Kissling via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> If guard defaults to something context-dependent, it's also counterintuitive.
>> 
>> 
>> Me personally is fine with guard x > 0 returning from the function in this case.
>> 
>> I use guard mainly as a glorified assert that allows safe exit from the function instead of crashing the program on fail.
>> If you think about it that way, it's perfectly reasonable that it returns in all cases.
>> 
>> 
>> 
>> On the other hand, the implicit default else behaviour could only trigger if there is no outer scope that can be exited with break.
>> Maybe OP could post additional statistics of the number cases where "guard ... else { return }" is used inside a breakable scope.
>> 
>> 
>> Etan
>> 
>> 
>> 
>> 
>> 
>>> On 16 Dec 2015, at 23:15, Vinicius Vendramini <vinivendra at gmail.com <mailto:vinivendra at gmail.com>> wrote:
>>> 
>>> Bringing up a possible edge case:
>>> 
>>> func foo() {
>>>     while(…) {
>>>         guard x > 0
>>>     }
>>> }
>>> 
>>> if guard defaulted to return even inside a while (as was suggested), this might be counterintuitive.
>>> 
>>>> On Dec 16, 2015, at 5:06 PM, Etan Kissling via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>> Also +1 on default return, -1 on default continue / break, and -1 for removing braces
>>>> 
>>>> Instead of VoidLiteralConvertible, one could extend on the idea with something that is not specifically tailored to nil, like
>>>> 
>>>> func foo(x: Int) -> Int = 5 {
>>>>     guard x < 10 // Would return default 5 for x >= 10
>>>> 
>>>>     if x > 5 {
>>>>         return // Would return default 5
>>>>     }
>>>>     return x
>>>> }
>>>> 
>>>> 
>>>> 
>>>> Etan
>>>> 
>>>> 
>>>>> On 16 Dec 2015, at 19:39, Ian Ynda-Hummel via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> 
>>>>> I am also +1 for implicit return, but -1 on continue/break for the reasons already stated.
>>>>> 
>>>>> I'm -1 for removing braces for one-liners. I think maintaining braces around blocks helps distinguish them from expressions. For example,
>>>>> 
>>>>>     guard x < 10 else return
>>>>> 
>>>>> would catch me off guard (pardon the pun).
>>>>> 
>>>>> I think I'm -1 on VoidLiteralConvertible, but I'm somewhat undecided. I think that separating the return value from the actual return point could lead to a lot of confusion, and would subsequently also make it easy to accidentally return the default value when you didn't intend to as the compiler wouldn't complain about a missing return value.  I don't think I have totally convinced myself that the latter is a non-trivial problem, but I thought it was worth mentioning.
>>>>> 
>>>>> On Wed, Dec 16, 2015 at 11:59 AM ilya via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> Actually I thought about VoidLiteralConvertible some more and now I think if we include it the only nontrivial case in the standard library case should be Optional.Nonel. Empty arrays and dictionaries are different
>>>>>  from nothing, so it's best to always return them explicitly. 
>>>>> 
>>>>> 
>>>>> 
>>>>> Oh, and it would help with default values, e.g.
>>>>> 
>>>>> 
>>>>> 
>>>>> var something:Something?
>>>>> 
>>>>> // where does the default value come from? VoidLiteralConvertible! 
>>>>> 
>>>>> 
>>>>> 
>>>>> I want all default values for String in this scope be "none":
>>>>> 
>>>>> 
>>>>> 
>>>>> private extension String: VoidLiteralConvertible { ... return "None" ... }
>>>>> 
>>>>> On Wed, Dec 16, 2015 at 10:49 ilya <ilya.nikokoshev at gmail.com <mailto:ilya.nikokoshev at gmail.com>> wrote:
>>>>> +1 on default return 
>>>>> 
>>>>> 
>>>>> 
>>>>> -1 on default continue or break, this is ambiguous. 
>>>>> 
>>>>> Even inside switch it's not clear if guard should break or return, so let's not make people guess. .
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> Also can we stop requiring braces for simple one-liners: 
>>>>> 
>>>>> 
>>>>> 
>>>>> guard x<10 else return 5
>>>>> 
>>>>> 
>>>>> 
>>>>> As for default return values, we could create a VoidLiteralConvertible, so that default return automatically becomes return nil or return [] in an Optional or Array context respectively. As a bonus, it will be technically possible to override this behavior
>>>>>  inside a specific function scope. 
>>>>> 
>>>>> 
>>>>> 
>>>>> > swift would provide a warning that the guard statement needs an else block
>>>>> 
>>>>> 
>>>>> 
>>>>> In this specific case the compiler basically has to guess, so an error seems more appropriate.
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> Ilya. 
>>>>> 
>>>>> On Wed, Dec 16, 2015 at 02:53 Vester Gottfried via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>>> I find myself writing the same else blocks for guard statements over and over again, so it might be reasonable to think about a default behaviour.
>>>>> 
>>>>> In a current project I found 217 guard statements from which 183 have repetitive else clauses
>>>>> 
>>>>> From which:
>>>>> 131 end with "else { return nil }"
>>>>> 44 "else { return }"
>>>>> 6 "else { continue }"
>>>>> 2 "else { break }"
>>>>> 
>>>>> My proposal would be to make the else block optional and define a default behaviour.
>>>>> 
>>>>> For example:
>>>>> 
>>>>> func foo(x: Int) {
>>>>> ​    ​ guard x < 10
>>>>> ​    ​ ...
>>>>> }
>>>>> 
>>>>> swift would implicitly add "else { return }"
>>>>> 
>>>>> --
>>>>> 
>>>>> func foo(x: Int) -> Int? {
>>>>> ​    ​ guard x < 10
>>>>> ​    ​ ...
>>>>> }
>>>>> 
>>>>> swift would implicitly add "else { return nil }"
>>>>> 
>>>>> --
>>>>> 
>>>>> for i in 0..<10 {
>>>>> ​    ​ guard i%2 == 0
>>>>> }
>>>>> 
>>>>> swift would implicitly add "else { continue }"
>>>>> 
>>>>> --
>>>>> 
>>>>> switch {
>>>>> case a :
>>>>> ​    ​ guard x != y
>>>>> case b :
>>>>> ​    ...​ 
>>>>> }
>>>>> 
>>>>> swift would implicitly add "else { break }"
>>>>> 
>>>>> --
>>>>> 
>>>>> func foo(x: Int) -> Int {
>>>>> ​    ​ guard x < 10
>>>>> ​    ​ ...
>>>>> }
>>>>> 
>>>>> swift would provide a warning that the guard statement needs an else block
>>>>> 
>>>>> --
>>>>> 
>>>>> Possible advantages
>>>>> - Less code ​ to write​ 
>>>>> - visually cleaner
>>>>> - ​ ​ In code with multiple guard statements ​ ​ you ​ ​ would not have to repeat the else block
>>>>> 
>>>>> 
>>>>> Possible Disadvantages
>>>>> - Different behaviour in different contexts (func/return, for/continue, switch/break, …) needs to be learned and understood
>>>>> - programmers might forget that guard + else {} is an option
>>>>>  _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <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 <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 <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 <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 <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 <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 <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 <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/24972308/attachment.html>


More information about the swift-evolution mailing list