[swift-evolution] ternary operator ?: suggestion

Alex Lew alexl.mail+swift at gmail.com
Sun Dec 6 21:45:24 CST 2015


I think the compiler can just assume that if it's valid to have a statement
in a given context, the if or switch should be interpreted as a statement.

A convention of keeping if-expressions to one line, and switch-expressions
to one line per case, would make things relatively readable (though I don't
feel that strongly about the convention):

let foo = if condition { function1() } else { function2() }
let foo = switch color {
    case .Red: function1()
    case .Green: function2()
    default: function3()
}

I'm still not totally convinced by Matthew's argument that making the
syntax lighter-weight is orthogonal to the expression/statement question.
In my mind, it makes sense to have both a heavier switch *statement*,
(which might have many sub-statements in each branch), and also a
lighter-weight option for a quick pattern-match inside an expression (like
the ones we've been discussing in this thread).

This is the whole idea behind the ternary operator in C, and the "a = value
if condition else otherValue" in Python, etc. That's why I kind of like the
ternary-operator-inspired syntax for pattern matching. It would be awful to
use for statements -- just like it would be awful to replace if/else
statements in C with the C ternary operator's syntax -- but I think it's
pretty readable for expressions. It just seems to fit: just like C's if,
while, for, and switch can now pattern match in Swift, so can ?: (not to
mention that the colons after each case "rhyme" with the original colon in
the ternary operator).

But I believe I'm in the minority on that opinion, which is totally fine. :)

I think the questions then become: first, as Chris has asked, do the
if/switch expressions provide enough of a benefit (in terms of conciseness)
to be worth implementing? And, as Matthew suggested: is there a
lighter-weight syntax that would make both statements and expressions more
succinct?

All best,
Alex

On Sun, Dec 6, 2015 at 10:11 PM, Paul Ossenbruggen <possen at gmail.com> wrote:

> In thinking about this, is there a way to have the compiler detect that
> something is a statement vs expression? Is it always clear to users when
> something is an expression vs a statement? In blurring the lines between
> expressions and statements complications arise anytime there is a return
> value returned by the result of “switch” or “if” it suddenly becomes an
> expression. Are there gray areas where it is hard to determine whether it
> is one vs the other when we use the those keywords? If it is not possible
> to determine for every situation or confusing to users, then maybe a new
> keyword for expressions is necessary. When a branch of an else returns void
> does it then become a statement? We should avoid shoehorning it in just to
> avoid another keyword.
>
> let foo = if condition {
> x = 1 // implied void -- illegal
> } else {
> 10  // returns expression
> }
>
> also, I think this is confusing:
>
> let foo = if condition {
> function1()
> } else {
> function2()
> }
>
> it is not obvious that this is an assignment or that the functions return
> anything. Earlier I suggested something using =  to make it more clear.
> This is similar to the requirement that functions that throw are prefixed
> with with “try"
>
> let foo if condition {
> = function1()
> } else {
> = function2()
> }
>
> also for the literal case:
>
> let foo  if condition {
> =  1 // can’t accidentally put a non expression here.
> } else {
> = 10  // returns expression
> }
>
> Which makes it clear that it is an expression coming back from both sides
> of the “if”. The switch case is a little trickier because of the case.
>
> let foo switch value {
> = .Red:   function1()
> = .Green  function2()
> =  default: function3()
> }
>
> The equal emphasizes the functions return a value for each part of the
> switch and assigns to “foo”, but somehow is unsatisfying having that equal
> everywhere.
>
> One the other hand,  the ternary operator being an expression this
> confusion does not exist, it is clear that function1() and function2() must
> return a value.
>
> let foo = condition ? function1() : function2()
>
> even when on separate lines:
>
> let foo = condition ?
> function1() :
> function2()
>
> So maybe Alex’s original suggestion works better where the ? operator is
> extended to support a switch like expression and keeping the two statements
> and expressions separate.
>
> let foo = condition ?
> .Red : .Green
> .Green : Red
>
> let foo = condition ?
> .Red: function1()
> .Green: function2()
>
> let foo = condition ? .Red: function1() .Blue: function2() default:.
> function3()
>
> also could include optional cases:
>
> let foo = condition ? case .Red: function1(), case .Blue: functions(),
> default: function3()
>
> Which brings us back full circle to the keyword because most people don’t
> like the ? operator which is why Alex suggested “match":
>
> let foo = match condition
> .Red: function1()
> .Green: function2()
> default: function3()
>
> or with optional cases:
>
> let foo = match condition
> case .Red: function1()
> case .Green: function2()
> default: function3()
>
> for booleans :
>
> let too = match condition function() else function2()
>
> I still like this better. A new keyword makes sure there is no confusion
> about expressions vs statements and avoids complications with the return
> values. Match would always be an expression, if/else/swtich are always
> statements. Also those keywords don’t change behavior if a user changes a
> statement into an expression by assigning the expression the else part
> would suddenly be required.
>
> if condition {
> function1()
> }
>
> is changed to
>
> let foo = if condition {
> function1()
> }
>
> is now an error, because there is no else. Now if function1() does not
> return a value. you have another error just changing it to assign
> completely changes the behavior of the “if” statement.
>
> - Paul
>
> On Dec 6, 2015, at 2:11 PM, Paul Ossenbruggen < possen at gmail.com> wrote:
>
> so the rule would have to be that the “switch" or “if" must return a value
> of compatible type. Not sure I love all the braces in the “if" case but it
> does follow the existing language rules with the exception that it must be
> have an else.
>
> let thisColor = if condition { .Red }   // illegal for expressions but not
> statements
>
> Can still do this for statements:
> if condition {
> x = 40
> }
>
> likewise:
> let thisColor = if condition { .Red } else { 21 } // illegal unless
> thisColor is Any
>
> unless:
> let thisColor : Any = if condition { .Red } else { 21 } // illegal unless
> thisColor is Any
>
> It would be nice to omit braces in this expression case but not for
> statements:
> let thisColor = if condition .Red else .Blue
>
> in statements braces would be required:
>
> if condition {
> x = 32
> } else {
> y = 44
> }
>
> >     }
>
> On Dec 6, 2015, at 1:52 PM, Alex Lew via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I agree that it's simplest to just reuse switch keyword, and keep braces.
> +1.
>
> Would you allow the same thing with if?
>
> let thisColor = if condition { .Red } else { .Blue }
>
> On Sun, Dec 6, 2015 at 4:44 PM, Rudolf Adamkovic   <salutis at me.com>  wrote:
>
>
>> > On 06 Dec 2015, at 22:35, thorsten--- via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>> >
>> > I would prefer the expression to match the statement. The only
>> difference would be that all parts that were statements now have to be
>> expressions.
>>
>> +1
>>
>> >
>> > Therefore the switch-expression should simply look like follows:
>> >
>> > let thisColor = switch thatColor {
>> >         case .Red: .Green // must be an expression
>> >         default: .Yellow      // must be an expression
>> >     }
>> >
>> > No returns needed in the case clauses.
>>
>> This actually looks great. One simple rule and zero new keywords.
>>
>> Readable and simple to learn.
>>
>> Fantastic!
>>
>> > Formatting this as a one-liner would just require adding semicolons
>> (though I wouldn't recommend this).
>> >
>> > -Thorsten
>> > _______________________________________________
>> > swift-evolution mailing list
>> >   swift-evolution at swift.org
>> >   https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151206/a0e7475e/attachment.html>


More information about the swift-evolution mailing list