- 
                Notifications
    
You must be signed in to change notification settings  - Fork 4.2k
 
Closed
Description
Background
Swift has a guard statement that can be very valuable in writing code that is easy to reason about. See Swift Guard Statement - why you should use it.
Problem
If we have a function Foo that takes an integer that must be positive (> 0), we can write that as:
Bar Foo_alt1(int b) {
    if (b > 0) {
        // all of our code is surrounded by checks for the condition.
        // special handling of condition is far away from the statement of what the condition is
        // extra indent, extra nesting, etc.
    } else {
        throw new IllegalArgumentException(nameof(b));
    }
}
Bar Foo_alt2(int b) {
    // 'syntactic sugar' disadvantage is that now we check for the "negative"
    // condition instead of the positive. this might be natural in cases of null checking or
    // other simple checks, but can become burdensome in complex cases of many comparisons
    // and logical operators.
    if (b <= 0) {
        throw new IllegalArgumentException(nameof(b));
    } else {
        // rest of code to handle the normal case is here.
        // 'excessive' nesting and indentation
        return foo;
    }
}
Bar Foo_alt3(int b) {
    // 'syntactic sugar' disadvantage is that now we check for the "negative"
    // condition instead of the positive. this might be natural in cases of null checking or
    // other simple checks, but can become burdensome in complex cases of many comparisons
    // and logical operators.
    if (b <= 0) {
        throw new IllegalArgumentException(nameof(b));
    }
    // rest of code to handle the normal case is here.
    // we choose not to resort to nesting, but in doing so, we lose an important compile-time check:
    // a programmer error might result in the if-block above not returning or throwing, thus
    // causing the control flow to drop off into the "normal" code
    return foo;
}Proposed Solution: guard statements
Bar Foo(int b) {
    // state that b must be a positive integer
    guard (b > 0) else {
        throw new IllegalArgumentException(nameof(b));
    }
    // compiler verifies that the guard-block throws or returns, thus
    // guaranteeing that code here will satisfy the guard condition.
    // ... do something with b without worrying about edge cases
}Benefits
The guard statement introduces two benefits over if-based guards:
- Syntactic sugar of declaring the positive condition we would like to meet after the guard, rather than the negatives
 - Compile-time checking of the fact that the guard clause ends control flow by returning or throwing
 - One less indent :)
 
Grammar
guard-statement
    : 'guard' ( boolean-expression ) 'else' embedded-statement
    ;