<div dir="ltr">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.<br><div><div class="gmail_extra"><br></div><div class="gmail_extra">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):</div><div class="gmail_extra"><br></div><div class="gmail_extra">let foo = if condition { function1() } else { function2() }</div><div class="gmail_extra">let foo = switch color {</div><div class="gmail_extra"> case .Red: function1()</div><div class="gmail_extra"> case .Green: function2()</div><div class="gmail_extra"> default: function3()</div><div class="gmail_extra">}</div><div class="gmail_extra"><br></div><div class="gmail_extra">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 <i>statement</i>, (which might have many sub-statements in each branch), and also<i> </i>a lighter-weight option for a quick pattern-match inside an expression (like the ones we've been discussing in this thread). </div><div class="gmail_extra"><br></div><div class="gmail_extra">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).</div><div class="gmail_extra"><br></div><div class="gmail_extra">But I believe I'm in the minority on that opinion, which is totally fine. :)</div><div class="gmail_extra"><br></div><div class="gmail_extra">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<i> </i>there a lighter-weight syntax that would make both statements and expressions more succinct?</div><div class="gmail_extra"><br></div><div class="gmail_extra">All best,</div><div class="gmail_extra">Alex</div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Dec 6, 2015 at 10:11 PM, Paul Ossenbruggen <span dir="ltr"><<a href="mailto:possen@gmail.com" target="_blank">possen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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.
<div><span class="">
<div>
<br>
</div>
<div>
let foo = if condition {
</div>
</span><div>
<span style="white-space:pre-wrap"> </span>x = 1 // implied void -- illegal
</div>
<div>
} else {
</div>
<div>
<span style="white-space:pre-wrap"> </span>10 // returns expression
</div>
<div>
}
</div>
<div>
<br>
</div>
<div>
also, I think this is confusing:
</div><span class="">
<div>
<br>
</div>
<div>
let foo = if condition {
</div>
</span><div>
<span style="white-space:pre-wrap"> </span>function1()
</div>
<div>
} else {
</div>
<div>
<span style="white-space:pre-wrap"> </span>function2()
</div>
<div>
}
</div>
<div>
<br>
</div>
<div>
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"
</div>
<div>
<br>
</div>
<div>
let foo if condition {
</div>
<div>
<div>
<span style="white-space:pre-wrap"> </span>= function1()
</div>
<div>
} else {
</div>
<div>
<span style="white-space:pre-wrap"> </span>= function2()
</div>
<div>
}
</div>
</div>
<div>
<br>
</div>
<div>
also for the literal case:
</div>
<div>
<br>
</div>
<div>
<div>
<div>
let foo if condition {
</div>
<div>
<span style="white-space:pre-wrap"> </span>= 1 // can’t accidentally put a non expression here.
</div>
<div>
} else {
</div>
<div>
<span style="white-space:pre-wrap"> </span>= 10 // returns expression
</div>
<div>
}
</div>
</div>
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
<div>
let foo switch value {
</div>
<div>
<span style="white-space:pre-wrap"> </span>= .Red: function1()
</div>
<div>
<span style="white-space:pre-wrap"> </span>= .Green function2()
</div>
<div>
<span style="white-space:pre-wrap"> </span>= default: function3()
</div>
<div>
}
</div>
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
let foo = condition ? function1() : function2()
</div>
<div>
<br>
</div>
<div>
even when on separate lines:
</div>
<div>
<br>
</div>
<div>
let foo = condition ?
</div>
<div>
<span style="white-space:pre-wrap"> </span>function1() :
</div>
<div>
<span style="white-space:pre-wrap"> </span>function2()
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
let foo = condition ?
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Red : .Green
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Green : Red
</div>
<div>
<br>
</div>
<div>
let foo = condition ?
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Red: function1()
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Green: function2()
</div>
<div>
<br>
</div>
<div>
<div>
let foo = condition ? .Red: function1() .Blue: function2() default:. function3()
</div>
</div>
<div>
<br>
</div>
<div>
also could include optional cases:
</div>
<div>
<br>
</div>
<div>
let foo = condition ? case .Red: function1(), case .Blue: functions(), default: function3()
</div>
<div>
<br>
</div>
<div>
Which brings us back full circle to the keyword because most people don’t like the ? operator which is why Alex suggested “match":
</div>
<div>
<br>
</div>
<div>
<div>
let foo = match condition
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Red: function1()
</div>
<div>
<span style="white-space:pre-wrap"> </span>.Green: function2()
</div>
</div>
<div>
<span style="white-space:pre-wrap"> </span>default: function3()
</div>
<div>
<br>
</div>
<div>
or with optional cases:
</div>
<div>
<br>
</div>
<div>
<div>
<div>
let foo = match condition
</div>
<div>
<span style="white-space:pre-wrap"> </span>case .Red: function1()
</div>
<div>
<span style="white-space:pre-wrap"> </span>case .Green: function2()
</div>
</div>
<div>
<span style="white-space:pre-wrap"> </span>default: function3()
</div>
</div>
<div>
<br>
</div>
<div>
for booleans :
</div>
<div>
<br>
</div>
<div>
let too = match condition function() else function2()
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
if condition {
</div>
<div>
<span style="white-space:pre-wrap"> </span>function1()
</div>
<div>
}
</div>
<div>
<br>
</div>
<div>
is changed to
</div><span class="">
<div>
<br>
</div>
<div>
let foo = if condition {
</div>
</span><div>
<span style="white-space:pre-wrap"> </span>function1()
</div>
<div>
}
</div>
<div>
<br>
</div>
<div>
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.
</div>
<div>
<br>
</div>
<div>
- Paul
</div><div><div class="h5">
<div>
<br>
</div>
<div>
<div>
<blockquote type="cite">
<div>
On Dec 6, 2015, at 2:11 PM, Paul Ossenbruggen <
<a href="mailto:possen@gmail.com" target="_blank">possen@gmail.com</a>> wrote:
</div>
<br>
<div>
<div style="word-wrap:break-word">
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.
<div>
<br>
</div>
<div>
let thisColor = if condition { .Red } // illegal for expressions but not statements
</div>
<div>
<br>
</div>
<div>
Can still do this for statements:
</div>
<div>
if condition {
</div>
<div>
<span style="white-space:pre-wrap"> </span>x = 40
</div>
<div>
}
<br>
<div>
<br>
</div>
<div>
likewise:
</div>
<div>
let thisColor = if condition { .Red } else { 21 } // illegal unless thisColor is Any
</div>
<div>
<br>
</div>
<div>
unless:
</div>
<div>
<div>
let thisColor : Any = if condition { .Red } else { 21 } // illegal unless thisColor is Any
</div>
</div>
<div>
<br>
</div>
<div>
It would be nice to omit braces in this expression case but not for statements:
</div>
<div>
let thisColor = if condition .Red else .Blue
</div>
<div>
<br>
</div>
<div>
in statements braces would be required:
</div>
<div>
<br>
</div>
<div>
if condition {
</div>
<div>
<span style="white-space:pre-wrap"> </span>x = 32
</div>
<div>
} else {
</div>
<div>
<span style="white-space:pre-wrap"> </span>y = 44
</div>
<div>
}
</div>
<div>
<br>
<blockquote type="cite">
<div class="gmail_extra">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"></blockquote>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"></blockquote>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"></blockquote>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span>> }</span>
</blockquote>
</div>
</div>
</blockquote>
<div>
<blockquote type="cite">
<div>
On Dec 6, 2015, at 1:52 PM, Alex Lew via swift-evolution <
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:
</div>
<br>
<div>
<div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
I agree that it's simplest to just reuse switch keyword, and keep braces. +1.
<div>
<br>
</div>
<div>
Would you allow the same thing with if?
<div>
<br>
</div>
<div>
let thisColor = if condition { .Red } else { .Blue }
</div>
</div>
</div>
<div class="gmail_extra" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br>
<div class="gmail_quote">
On Sun, Dec 6, 2015 at 4:44 PM, Rudolf Adamkovic
<span> </span>
<span dir="ltr"><<a href="mailto:salutis@me.com" target="_blank">salutis@me.com</a>></span>
<span> </span>wrote:
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span>> On 06 Dec 2015, at 22:35, thorsten--- via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br><br>><br>> 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.<br><br></span>+1
<br>
<span><br>><br>> Therefore the switch-expression should simply look like follows:<br>><br>> let thisColor = switch thatColor {<br>> case .Red: .Green // must be an expression<br>> default: .Yellow // must be an expression<br>> }<br>><br>> No returns needed in the case clauses.<br><br></span>This actually looks great. One simple rule and zero new keywords.
<br>
<br>Readable and simple to learn.
<br>
<br>Fantastic!
<br>
<span><br>> Formatting this as a one-liner would just require adding semicolons (though I wouldn't recommend this).<br>><br>> -Thorsten<br></span>
<div>
<div>
> _______________________________________________
<br>> swift-evolution mailing list
<br>>
<span> </span>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>
<br>>
<span> </span>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a>
<br>
</div>
</div>
</blockquote>
</div>
<br>
</div>
<span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important"><span> </span>_______________________________________________</span>
<br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">swift-evolution mailing list</span>
<br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<a href="mailto:swift-evolution@swift.org" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">swift-evolution@swift.org</a>
<br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a>
</div>
</blockquote>
</div>
</div></div></div></div></blockquote></div></div></div></div></div></blockquote></div><br></div></div></div>