Pitch: Multi-statement if/switch/do expressions

Having

/* let x = */ <expression>

either return from an outer function / closure or not depending upon whether /* let x = */ is commented or not sounds totally weird proposition to me.


I suggest these two bullet points being considered:

  • forgetting the usage of "return" to mean expression value (which is totally bonkers IMHO), whether to allow or prohibit "return" to return from the outer function / closure scope is not so obvious. We can use "fatalError" or "throw", why not return?
func foo() throws -> Int {
    let x = if condition { 42 }
    else { fatalError("xxx") } // ✅

    let y = if condition { 42 }
    else { throw xxx } // ✅

    let z = if condition { 42 }
    else { return 24 } // 🛑 🤯
}

  • whether to allow more than one "exit" from a single branch and whether to run the code after an exit:

    1. "pascal" option. Allow more than one "exit" from a single branch. The code after "exit" still runs
let x = if condition {
    then 42 // default value
    print("42") // prints 42
    if subCondition {
        then 24
        print("24") // prints 24
    }
    // expression result is 24 when subCondition is true
} else {
    0
}
  1. prohibit more than one "exit" from a single branch. No code runs after the first "exit":
let x = if condition {
    then 42 // default value
    print("42") // the code is unreachable warning 
    if subCondition { // the code is unreachable warning 
        then 24 // error
        print("24") // the code is unreachable warning 
    }
    // expression result is 42
} else {
    0
}
  1. allow more than one "exit" from a single branch. The code after "exit" does not run:
let x = if condition {
    if subCondition {
        then 42 // expression result is 42
        print("42") // warning: this code is unreachable
    }
    if otherCondition {
        then 24 // expression result is 24
        print("24") // warning: this code is unreachable
    }
    then 123 // expression result is 123
    print("123") // warning: this code is unreachable
}

whether to allow more than one "exit" point from a single branch and separate to that but equally important whether the code after "exit" is being run or not – is not mentioned in the proposal. Note that only option #2 allows "a bare last expression" rule. Note that a similar thing was allowed in Pascal which chose option #1 from the above option list:

FUNCTION FOO: INTEGER
BEGIN
    FOO := 42; // default value
    IF subCondition THEN BEGIN
        FOO := 24
    END
END;
1 Like