[swift-evolution] the "guard" keyword, again

Dave Yost Dave at Yost.com
Tue Jun 21 00:04:54 CDT 2016


In the Commonly Rejected Changes <https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md> page and in this swift-evolution email <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005534.html> to which it refers, I read that first there was “unless", then “require” then finally “guard ... else”.

I couldn’t find the earlier discussion in which “unless” was replaced for a while by “require”, so I am moved to ask, “Was there ever “require … else”, or was it just “require”? I’ll assume it was just “require”.

There are various problems with the choice of the keyword “guard”. These have bothered me every since I first saw it.



Problems:
If we’re reading “guard” as a verb, then we expect the object to come right after it, but it doesn’t; you can’t say you’re guarding the condition-clause. No, what you’re guarding is the code after the entire guard-statement.
The “else” after guard suggests that the else code covers what to do when the guard fails, but the guard doesn’t fail in the “else”; the guarding works correctly on both execution paths.
The “guard” keyword gives no hint really as to whether the condition is required or prohibited; you figure that out only be thinking about why there is an “else” clause. The guard statement is intended to replace typical code in the wild that uses an “if” statement that is written to abort when the condition fails, not when it succeeds.


Proposed
   require count >= 0 else { return }
Replaces
   guard count >= 0 else { return }
Unambiguously equivalent to
   if count < 0 { return }

Benefits of “require … else”:
The word “require” states more clearly and strongly than “guard” that it is an ultimatum.
The word “require” conveys clearly that the require-statement can block the following statement from executing.
The condition-clause functions as the object of the verb “require”, so it reads well as natural language.
The sense of the condition-clause is clear; success is required before executing the next statement.
The “else” after “require” clearly introduces code to run if the requirement is not met.
With the new comma syntax for conditions, the word “require” fits well with the fact that all conditions in the list are, shall we say, required.
When one of the conditions is a let, “require” conveys the idea that the declaration will be required and thus will have a lifetime beyond the require-statement.

It would still be OK to refer to a require-statement as a “guard clause", to invoke the history of guarding. But even here, I think “require clause” is clearer (see last bullet point). Evoking the historical use of the term “guard” for this construct in Swift is not such a great argument because (a) the term is not that well known, and (b) the term has not always been used for clearly the same purpose. Dijkstra’s use of the term <https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if>, for example, was a bit different, allowing for nondeterministic execution.

In summary, “require … else” is a very clean choice and beats “guard ... else” handily.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160620/093fa290/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PastedGraphic-1.png
Type: image/png
Size: 14792 bytes
Desc: not available
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160620/093fa290/attachment.png>


More information about the swift-evolution mailing list