[swift-evolution] ternary operator ?: suggestion

Paul Ossenbruggen possen at gmail.com
Sun Dec 6 21:11:36 CST 2015


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 <mailto: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 <mailto:salutis at me.com>> wrote:
>> > On 06 Dec 2015, at 22:35, thorsten--- via swift-evolution <swift-evolution at swift.org <mailto: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 <mailto:swift-evolution at swift.org>
>> > https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>>  _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <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/e55ec65c/attachment.html>


More information about the swift-evolution mailing list