[swift-evolution] ternary operator ?: suggestion

Kevin Ballard kevin at sb.org
Sat Dec 5 21:53:44 CST 2015

On Sat, Dec 5, 2015, at 04:32 PM, Lukas Stabe via swift-evolution wrote:
>> I don't think you can just get rid of the if statement in favor of an
>> expression. You still want to be able to do this:
>> if (condition) {    funcWithSideEffectsThatReturnsInt() } else {
>> funcWithSideEffectsThatReturnsString() }
>> but that's not a valid expression (what is its type?).
> An if statement with two different types could just have the closes
> common ancestor or Any as type.

That's a great way to cause confusion.

Rust has this feature (all statements are expressions), and it requires
if statements to have an else branch with the same type unless the type
is `()`. It's solution to the issue of the branches returning unwanted
values is that Rust uses semicolons, and the semicolon acts sort of like
an operator that consumes any value and returns `()`, so if you
terminate the last statement of the branch with a semicolon, the whole
branch returns `()`, and if you leave it off, the branch returns a
value. It's actually very elegant and straightforward.

That said, proposing that Swift introduce this same rule for semicolons
is probably not a good idea. We certainly could declare that an explicit
semicolon has this behavior, so you'd see people writing code like

if condition {    funcWithSideEffectsThatReturnsInt(); }

but it would be confusing because semicolons are almost never
used in Swift.

An alternative that would work today is just relying on assignment
returning Void, so you can write

if condition {    _ = funcWithSideEffectsThatReturnsInt() }

but that looks kind of weird and would probably also be confusing.
Better than the semicolon rule I think, but still not great.

Another option is to check if the return value is actually used
anywhere, and if it's not, then silently coerce it to Void. This way
you can write

if condition {    funcWithSideEffectsThatReturnsInt() } else {
funcWithSideEffectsThatReturnsString() }

and it would be fine but writing

let foo = if condition {    funcWithSideEffectsThatReturnsInt() } else {
funcWithSideEffectsThatReturnsString() }

would fail with a type error.

I suspect that this is the right approach, but it does involve a
bit of magic.

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

More information about the swift-evolution mailing list