[Idea] Wrap switch cases in curly braces


(G B) #1

It has always seemed odd to me that `case`s use a colon as a delimiter rather than curly braces like everything else. Is there a reason for this other than the legacy of C-like languages?

If I wanted to write a series of branching `if` \ `else` statements I would do it like so:

if x==0 { print(0) }
else if x==1 { print (1) }
else if x==2 { print(2) }
else { print("other”) }

I believe all flow control is wrapped in curly braces, except for `case`s inside a `switch`:

switch x {
case 0: print(0)
case 1: print(1)
case 2: print(2)
default: print("other")
}

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.


(Brandon Knope) #2

When each case only takes up one line, it may look nice and concise. But what happens in the common case when your case takes up more lines and you indent your braces?

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

switch x {
case 0 {
    print(0)
}
case 1 {
    print(1)
}
case 2 {
    print(2)
}
default {
    print("other”)
}
}

I think this looks much heavier and harder to read. All the braces detract from the important stuff

Brandon

···

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Roth Michaels) #3

I sort of see what you are saying about `case` not seeming like a label
since we don't have GOTO in Swift.

I prefer the colon vs your brace suggestion, because from my
perspective, the `switch` expression is the control flow statement and
to the cases are like some sort of label even if they include complex
pattern matching.

While Scala drops the colon to avoid case statements looks like labels,
but uses => instead of whitespace and {} --- I prefer this to your
suggestion, but as I said also think the colon is fine.

···

On Thu, Jul 07 2016 at 04:07:06 PM, G B via swift-evolution <swift-evolution@swift.org> wrote:

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

The colon syntax evokes a label, but the modern, complex `case`
statements in Swift don’t act much like labels.

--
Roth Michaels
roth@rothmichaels.us


(Jon Akhtar) #4

You can have this now:

switch x {
case 0: { print(0) }()
case 1: { print(1) }()
case 2: { print(2) }()
default: { print("other²) }()
}

However it isn¹t quite the same.

Case with a colon has far too many parallels in other very common
languages IMHO. I am not sure being consistent is always a must, it should
add something, ease of understanding, readability, etc. I don¹t think
braces here really do. Like I mentioned though, you can have them now if
you don¹t mind the extra parens.

Cheers

On 7/7/16, 13:07, "swift-evolution-bounces@swift.org on behalf of G B via
swift-evolution" <swift-evolution-bounces@swift.org on behalf of

···

swift-evolution@swift.org> wrote:

It has always seemed odd to me that `case`s use a colon as a delimiter
rather than curly braces like everything else. Is there a reason for
this other than the legacy of C-like languages?

If I wanted to write a series of branching `if` \ `else` statements I
would do it like so:

if x==0 { print(0) }
else if x==1 { print (1) }
else if x==2 { print(2) }
else { print("other²) }

I believe all flow control is wrapped in curly braces, except for `case`s
inside a `switch`:

switch x {
case 0: print(0)
case 1: print(1)
case 2: print(2)
default: print("other")
}

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other²) }
}

The colon syntax evokes a label, but the modern, complex `case`
statements in Swift don¹t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #5

While I could maybe see this being an option, we already kind of have it thanks to do{} blocks:

  switch x {
    case 0: do {
      print(0)
    }
    case 1: do {
      print(1)
    }
    case 2: do {
      print(2)
    }
    default: do {
      print("other")
    }
  }

Not quite as pretty, but perfectly functional right now, but will many people use it if given the chance? If you need scoping then you probably have conditionals anyway, or you can just do{} blocks for those cases only, I don't really see the need to require them on all of them.

Personally I don't see the need; the case labels themselves are highlighted pretty clearly thanks to being keywords, and act as both the opening for their block, and the close of any previous block, meanwhile the whole switch has enclosing braces already. There's also the issue of scope; you can fall through from a case, so technically speaking the only scope may be the switch itself, as you could fall through every single case and thus visit everything on the way down.

So yeah, I think the construct kind of already makes sense as it is, it's just a bit of weird one conceptually.

···

On 7 Jul 2016, at 21:07, G B via swift-evolution <swift-evolution@swift.org> wrote:

It has always seemed odd to me that `case`s use a colon as a delimiter rather than curly braces like everything else. Is there a reason for this other than the legacy of C-like languages?

If I wanted to write a series of branching `if` \ `else` statements I would do it like so:

if x==0 { print(0) }
else if x==1 { print (1) }
else if x==2 { print(2) }
else { print("other”) }

I believe all flow control is wrapped in curly braces, except for `case`s inside a `switch`:

switch x {
case 0: print(0)
case 1: print(1)
case 2: print(2)
default: print("other")
}

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.


(David Sweeris) #6

What would be the proposed syntax for cases with associated values?

In general, +1 for simplifying the syntax, but I'm not sure it'd work well, given that enums take on a larger roll in Swift than they do in other languages. Or maybe it'd be fine... I'm just too tired to picture it in my head.

- Dave Sweeris

···

On Jul 7, 2016, at 15:07, G B via swift-evolution <swift-evolution@swift.org> wrote:

It has always seemed odd to me that `case`s use a colon as a delimiter rather than curly braces like everything else. Is there a reason for this other than the legacy of C-like languages?

If I wanted to write a series of branching `if` \ `else` statements I would do it like so:

if x==0 { print(0) }
else if x==1 { print (1) }
else if x==2 { print(2) }
else { print("other”) }

I believe all flow control is wrapped in curly braces, except for `case`s inside a `switch`:

switch x {
case 0: print(0)
case 1: print(1)
case 2: print(2)
default: print("other")
}

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#7

I don’t like this idea at all. The current switch syntax is really clean, one of the nicest parts of Swift, and this would really turn it into something messy.

I’ll make a possibly controversial statement here: one of the worst aspects of C syntax, which is unfortunately perpetuated by many modern languages, Swift included, is the use of curly braces everywhere to demarcate every kind of block: every control structure, every data structure and every function body.

This leads to a proliferation of nested braces which all have to be placed correctly in order for the code to be correct. Of course, we all use indentation to help manage this, but I think we all know that once the closing brace is sufficiently far from the opening brace, it becomes difficult to tell which brace matches which even with indentation. I think I spend a significant amount of my development time just eyeballing those closing braces. Of course, we also have editor features to help match them up but relying on such editor features might be an indication of a flaw in the language. At any rate, it impedes readability of the code, editor or no editor.

Not having the braces for each case is, to me, analogous to the way Swift removed the outermost parenthesis in the if statement conditional part. When you have a complex conditional expression with nested parentheses, removing that unnecessary outermost pair really improves readability (and reduces possibility of error). This can be done because the outermost parentheses aren’t really necessary to demarcate the boundaries of the expression.

Similarly, the case keywords in the switch statement sufficiently demarcate the extent of the statement block; it is unnecessary to toss in an extra pair of these brace characters that may already be heavily used in the statement block itself.

I think the extra burden on readability (and writability) of having the extra pair of nested braces is not justified by the desire for consistency. If consistency is so important, then rather than detracting from the quality of the switch statement by adding the braces, why don’t we improve the quality of the rest of the language by getting rid of some of those braces in the other constructs that use them! (Note: I don’t really expect that to happen…)

- Dennis D.


(G B) #8

The same can be said for if/else constructs though— all those braces get heavy if they’re all wrapping one line each. Python does away with the braces and relies on indentation, but Swift has explicitly stated that it will not follow that path— yet case statements seem an exception. It’s a collection of statements, they should be grouped in braces.

Your example is still only one line per case, but those braces are less of a problem when amortized over more lines (note that there are extra braces enforced by the `if` and `else`):

switch x {
case 0 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}

case 1 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(1)
    }
}

case 2 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(2)
    }
}

default {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}
}

···

On Jul 7, 2016, at 13:24 , Brandon Knope <bknope@me.com> wrote:

When each case only takes up one line, it may look nice and concise. But what happens in the common case when your case takes up more lines and you indent your braces?

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

switch x {
case 0 {
    print(0)
}
case 1 {
    print(1)
}
case 2 {
    print(2)
}
default {
    print("other”)
}
}

I think this looks much heavier and harder to read. All the braces detract from the important stuff

Brandon

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #9

But they *are* separate scopes. A `let` in one case doesn't remain available in the next.

I prefer braces to colons, but I think I've made this argument before and lost to the "we don't deviate from C just for the hell of it" rule.

···

On Jul 7, 2016, at 2:05 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

There's also the issue of scope; you can fall through from a case, so technically speaking the only scope may be the switch itself, as you could fall through every single case and thus visit everything on the way down.

--
Brent Royal-Gordon
Architechies


(Brandon Knope) #10

But in general, if I use enums, I have more cases than I normally would have of if-else statements.

I try not to have many if-else chains but I generally have 2+ cases which would result in more braces than my typical if-else

···

On Jul 7, 2016, at 4:41 PM, G B via swift-evolution <swift-evolution@swift.org> wrote:

The same can be said for if/else constructs though— all those braces get heavy if they’re all wrapping one line each. Python does away with the braces and relies on indentation, but Swift has explicitly stated that it will not follow that path— yet case statements seem an exception. It’s a collection of statements, they should be grouped in braces.

Your example is still only one line per case, but those braces are less of a problem when amortized over more lines (note that there are extra braces enforced by the `if` and `else`):

switch x {
case 0 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}

case 1 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(1)
    }
}

case 2 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(2)
    }
}

default {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}
}

On Jul 7, 2016, at 13:24 , Brandon Knope <bknope@me.com <mailto:bknope@me.com>> wrote:

When each case only takes up one line, it may look nice and concise. But what happens in the common case when your case takes up more lines and you indent your braces?

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

switch x {
case 0 {
    print(0)
}
case 1 {
    print(1)
}
case 2 {
    print(2)
}
default {
    print("other”)
}
}

I think this looks much heavier and harder to read. All the braces detract from the important stuff

Brandon

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

Fallthrough ceases to make much sense with braces, and it is a handy
feature of switch statements every so often.

···

On Thu, Jul 7, 2016 at 15:31 Roth Michaels via swift-evolution < swift-evolution@swift.org> wrote:

On Thu, Jul 07 2016 at 04:07:06 PM, G B via swift-evolution < > swift-evolution@swift.org> wrote:
> I feel like this would be more consistent with the rest of the syntax:
>
> switch x {
> case 0 { print(0) }
> case 1 { print(1) }
> case 2 { print(2) }
> default { print("other”) }
> }
>
> The colon syntax evokes a label, but the modern, complex `case`
> statements in Swift don’t act much like labels.

I sort of see what you are saying about `case` not seeming like a label
since we don't have GOTO in Swift.

I prefer the colon vs your brace suggestion, because from my
perspective, the `switch` expression is the control flow statement and
to the cases are like some sort of label even if they include complex
pattern matching.

While Scala drops the colon to avoid case statements looks like labels,
but uses => instead of whitespace and {} --- I prefer this to your
suggestion, but as I said also think the colon is fine.

--
Roth Michaels
roth@rothmichaels.us

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(G B) #12

I’d imagine it would be the same just without the colon and with the braces:

enum MyEnum {
    case IntEnum(Int)
    case StringEnum(String)
}

var x=MyEnum.StringEnum("Hello")

switch x {
    case .IntEnum(let x) {
        print(x)
    }

    case .StringEnum(let x) {
        print(x)
    }

}

Not much different than:

if case .StringEnum(let v) = x {
    print(v+" again")
}

except that the switch compares all case statements against x.

···

On Jul 7, 2016, at 10:37 PM, David Sweeris <davesweeris@mac.com> wrote:

What would be the proposed syntax for cases with associated values?

In general, +1 for simplifying the syntax, but I'm not sure it'd work well, given that enums take on a larger roll in Swift than they do in other languages. Or maybe it'd be fine... I'm just too tired to picture it in my head.

- Dave Sweeris

On Jul 7, 2016, at 15:07, G B via swift-evolution <swift-evolution@swift.org> wrote:

It has always seemed odd to me that `case`s use a colon as a delimiter rather than curly braces like everything else. Is there a reason for this other than the legacy of C-like languages?

If I wanted to write a series of branching `if` \ `else` statements I would do it like so:

if x==0 { print(0) }
else if x==1 { print (1) }
else if x==2 { print(2) }
else { print("other”) }

I believe all flow control is wrapped in curly braces, except for `case`s inside a `switch`:

switch x {
case 0: print(0)
case 1: print(1)
case 2: print(2)
default: print("other")
}

I feel like this would be more consistent with the rest of the syntax:

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Peter Eddy) #13

I appreciate the desire for consistency but I really don't like this
proposal. I agree with others who've said that it makes the code look heavy
and that the extra parens only obscure the actual code, at least when the
code is short. I don't think there is any way in which the parens make the
code clearer, they're just visual noise.

If we insist on consistency then shouldn't we also do away with implicit
returns from single-expression closures? After all this behavior is
inconsistent with named functions. And shouldn't closures also declare
their signature before their opening brace, rather than after, also to be
consistent with named functions?

All these breaks with consistency have the effect of making the language
easier and more pleasant to read, and they don't seem to be major stumbling
blocks for people learning Swift. I hate to see them go away.

- Peter

···

On Fri, Jul 8, 2016 at 1:58 AM, G B via swift-evolution < swift-evolution@swift.org> wrote:

I’d imagine it would be the same just without the colon and with the
braces:

enum MyEnum {
    case IntEnum(Int)
    case StringEnum(String)
}

var x=MyEnum.StringEnum("Hello")

switch x {
    case .IntEnum(let x) {
        print(x)
    }

    case .StringEnum(let x) {
        print(x)
    }

}

Not much different than:

if case .StringEnum(let v) = x {
    print(v+" again")
}

except that the switch compares all case statements against x.

> On Jul 7, 2016, at 10:37 PM, David Sweeris <davesweeris@mac.com> wrote:
>
> What would be the proposed syntax for cases with associated values?
>
> In general, +1 for simplifying the syntax, but I'm not sure it'd work
well, given that enums take on a larger roll in Swift than they do in other
languages. Or maybe it'd be fine... I'm just too tired to picture it in my
head.
>
> - Dave Sweeris
>
>> On Jul 7, 2016, at 15:07, G B via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> It has always seemed odd to me that `case`s use a colon as a delimiter
rather than curly braces like everything else. Is there a reason for this
other than the legacy of C-like languages?
>>
>> If I wanted to write a series of branching `if` \ `else` statements I
would do it like so:
>>
>> if x==0 { print(0) }
>> else if x==1 { print (1) }
>> else if x==2 { print(2) }
>> else { print("other”) }
>>
>> I believe all flow control is wrapped in curly braces, except for
`case`s inside a `switch`:
>>
>> switch x {
>> case 0: print(0)
>> case 1: print(1)
>> case 2: print(2)
>> default: print("other")
>> }
>>
>>
>> I feel like this would be more consistent with the rest of the syntax:
>>
>> switch x {
>> case 0 { print(0) }
>> case 1 { print(1) }
>> case 2 { print(2) }
>> default { print("other”) }
>> }
>>
>> The colon syntax evokes a label, but the modern, complex `case`
statements in Swift don’t act much like labels.
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(G B) #14

The discussion so far has given me a chance to organize my thinking, so here’s a more complete train of thought.

I get that people don’t like extra punctuation. The commonly rejected proposals, however, make it clear that braces are here to stay and we should be designing the syntax right now with that in mind. It took me a long time to get used to not using them in Python, now I’m getting used to using them again in Swift. Swift has a long life ahead of it, and there are going to be plenty of places where the syntax is going to become inconsistent in the service of supporting new features. Now is when we set the starting point though and try to set ourselves up in a way that requires a minimum of syntax goofs in the future.

—=Philosophy=—

As philosophical backdrop, here’s the link on removing braces in the “commonly rejected proposals” section:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003656.html

I’ll pull out two quotes from that post, one from Kevin Ballard:
"There is not in fact an emphasis on conciseness. This has been repeated many times by the swift team. Conciseness is not a goal of Swift, but expressiveness absolutely is. Braces are a well-understood and simple way to express the notion of a scope/closure.”

and another edited as suggested by Chris Lattner:
"'Be like C' isn't a goal either of course, but when deciding between two alternatives that have no compelling arguments either way, picking the one that is most familiar to programmers in the extended C family is a good idea."

So, from that I take:
1) braces indicate scoping
2) conciseness isn’t an end in itself
3) we should err on the side of being Cish when no other arguments prevail.

—=In C `cases` Aren’t Scopes, in Swift They Are=—

Starting from what’s Cish, here’s a snippet of Swift code:

let x=5
switch x {
  case 3:
    let y=5
    print(x," ",y)

  case 5:
    print("Two",x,"s”)

  default:
    print(“default")
}

This runs fine and prints “Two 5 s” to the console.

This is something similar in C:

int x=5;
switch (x) {
  case 3:
    int y=5;
    printf("%d %d",x,y);
    break;

  case 5:
    printf("Two %d s",x);
    break;

  default:
    printf(“default");
}

This code fails. C gives me an error pointing at `int y=5;` complaining that it expected an expression there. C++ gives me an error that it can’t jump to `case 5:` because it would skip over the declaration of `y`.

I can fix this in both C and C++ by wrapping the `case 3:` in curly braces, creating a local scope:

int x=5;
switch (x) {
  case 3: {
    int y=5;
    printf("%d %d",x,y);
    break;
  }

  case 5:
    printf("Two %d s",x);
    break;

  default:
    printf("default");
}

This code compiles fine in both C and C++. A new scope has been delimited and created, and `y` only exists in that scope.

So, by both criteria 1) and 3), Swift should be using braces on `case` statements. Each case is a scope unto itself, and the extended C family of languages would require braces in that event.

—=Conciseness, Ugliness and Nested Braces=—

Conciseness is not an emphasis of Swift, but even if it were then this is not a particularly in-concise change to the syntax. The suggestion here is to remove one punctuation mark and add two for a net gain of 1 character. This doesn’t strike me as unduly burdensome.

The better arguments are those on aesthetics and ease of use. Each of these seems to focus on opposite situations. The ugliness is when there is only one line per case, the ease of use challenge is when there are many and the developer needs to determine how many braces to close.

How common is it to have a single line per case?

Aesthetics, at least, are mostly subjective. Ease of use, in part, depends on habits. In both cases, however, I’d argue that the aesthetically preferable design, and the method least likely to introduce errors, is the one that is most consistent with the rest of the language. Things tend to be uglier when they stand out as unusual, and habits force us to follow patterns, introducing errors when the pattern doesn’t hold.

From that perspective, this is what Swift looks like everywhere else:

if x = 3 { print(“Three”) }
else if x = 5 { print(“Five”) }
else { print(“Default”) }

It also doesn’t shy away from nested braces:

var x:Int {
  get { return _x }
  set { _x = newValue }
}

Aesthetically, is it less ugly to have some scopes require braces and others not? I really thought the square bracket messaging syntax of Obj-C was ugly until I got used to it because square brackets were for subscripting and looked “heavy” for method calls.

From an ease of use perspective, it is more likely to forget to add a closing brace when braces are used everywhere, or to accidentally add one in the one place they aren’t?

—=What Isn’t Like C Shouldn’t Look Like C=—

There’s also the point that `switch` statements in Swift aren’t the same as those in C. The different scoping rules are one difference. The lack of default fall through is another. And of course the additional capabilities of the `case` condition itself.

For those reasons, deviating from the C syntax might not only be justified, but desirable as a notational reminder that this isn’t your father’s `switch` statement. The closing brace in particular gives a visual cue that fall through isn’t going to happen.

—=Leaving the Door Open for a `switch` Expression=—

Another commonly rejected proposal is the request for a `switch` expression:
https://lists.swift.org/pipermail/swift-evolution/2015-December/000393.html

To my eyes, the rejection of this proposal is not as iron clad as the rejection of removing curly braces. Here’s a quote from Chris Lattner:

"FWIW, I (and many other people) would like to consider turning many statement-y things in swift into expressions. I’d love to see the weird ?: ternary operator get nuked and replaced with an if/else expression of some sort. This is an area that the apple team hasn’t had bandwidth to consider carefully.

That said, there are challenges here in the details. How will the grammar work?”

I think wrapping the `case` statements in curly braces in the statement version of `switch` gets us closer to a reasonable answer for how the grammar might work on an expression version: the expression version would be delimited with colons similar to how the ternary operator is.

Something like this might work:

let s:String? = switch x
                case 3: “Three”
                case 5: “Five”
                default: nil

In the expression, the `case` clauses don’t represent scopes and shouldn’t be curly braced so the colons give a nice syntactic distinction.

I’m not holding by breath for such a feature, but this change to the `switch` statement makes such a thing easier to adopt.

···

On Jul 10, 2016, at 13:37 , Dennis De Mars <demars@fractaldomains.com> wrote:

I don’t like this idea at all. The current switch syntax is really clean, one of the nicest parts of Swift, and this would really turn it into something messy.

I’ll make a possibly controversial statement here: one of the worst aspects of C syntax, which is unfortunately perpetuated by many modern languages, Swift included, is the use of curly braces everywhere to demarcate every kind of block: every control structure, every data structure and every function body.

This leads to a proliferation of nested braces which all have to be placed correctly in order for the code to be correct. Of course, we all use indentation to help manage this, but I think we all know that once the closing brace is sufficiently far from the opening brace, it becomes difficult to tell which brace matches which even with indentation. I think I spend a significant amount of my development time just eyeballing those closing braces. Of course, we also have editor features to help match them up but relying on such editor features might be an indication of a flaw in the language. At any rate, it impedes readability of the code, editor or no editor.

Not having the braces for each case is, to me, analogous to the way Swift removed the outermost parenthesis in the if statement conditional part. When you have a complex conditional expression with nested parentheses, removing that unnecessary outermost pair really improves readability (and reduces possibility of error). This can be done because the outermost parentheses aren’t really necessary to demarcate the boundaries of the expression.

Similarly, the case keywords in the switch statement sufficiently demarcate the extent of the statement block; it is unnecessary to toss in an extra pair of these brace characters that may already be heavily used in the statement block itself.

I think the extra burden on readability (and writability) of having the extra pair of nested braces is not justified by the desire for consistency. If consistency is so important, then rather than detracting from the quality of the switch statement by adding the braces, why don’t we improve the quality of the rest of the language by getting rid of some of those braces in the other constructs that use them! (Note: I don’t really expect that to happen…)

- Dennis D.


(G B) #15

Braces don’t preclude using `break` or `continue`, why would they preclude `fallthrough`?

···

On Jul 7, 2016, at 13:33 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Fallthrough ceases to make much sense with braces, and it is a handy feature of switch statements every so often.
On Thu, Jul 7, 2016 at 15:31 Roth Michaels via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Thu, Jul 07 2016 at 04:07:06 PM, G B via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I feel like this would be more consistent with the rest of the syntax:
>
> switch x {
> case 0 { print(0) }
> case 1 { print(1) }
> case 2 { print(2) }
> default { print("other”) }
> }
>
> The colon syntax evokes a label, but the modern, complex `case`
> statements in Swift don’t act much like labels.

I sort of see what you are saying about `case` not seeming like a label
since we don't have GOTO in Swift.

I prefer the colon vs your brace suggestion, because from my
perspective, the `switch` expression is the control flow statement and
to the cases are like some sort of label even if they include complex
pattern matching.

While Scala drops the colon to avoid case statements looks like labels,
but uses => instead of whitespace and {} --- I prefer this to your
suggestion, but as I said also think the colon is fine.

--
Roth Michaels
roth@rothmichaels.us <mailto:roth@rothmichaels.us>

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(G B) #16

Don’t get me wrong, I’m not a huge fan of having extra punctuation around, but as a matter of syntactic consistency, it seems the right thing to do. It’s adding a single character (less than the `do` alternative that some are suggesting.

It seems like the arguments against it are the same as the arguments for eliminating curly braces entirely— they’re ugly. However it’s been decided that we’re going to use curly braces everywhere but here.

As an instructor, I’m not sure how I would explain to a student why everywhere else there is the potential for more than one statement in a syntactic slot they should use curly braces but that `case` is the sole exception because somebody did it that way in the 70’s. We’ve already decided to throw away legacy C syntax in `for` loops, why not here while we have a shot at consistency?

Is there anywhere else that a sequence of statements isn't wrapped?

for <#item#> in <#items#> {
    <#code#>
}

if <#condition#> {
    <#code#>
} else if <#condition#> {
    <#code#>
} else {
    <#code#>
}

while <#condition#> {
    <#code#>
}

repeat {
    <#code#>
} while <#condition#>

var x:Type {
get {
    return _x
}
set {
    _x=newValue
}
}

···

On Jul 7, 2016, at 13:47 , Brandon Knope <bknope@me.com> wrote:

But in general, if I use enums, I have more cases than I normally would have of if-else statements.

I try not to have many if-else chains but I generally have 2+ cases which would result in more braces than my typical if-else

On Jul 7, 2016, at 4:41 PM, G B via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The same can be said for if/else constructs though— all those braces get heavy if they’re all wrapping one line each. Python does away with the braces and relies on indentation, but Swift has explicitly stated that it will not follow that path— yet case statements seem an exception. It’s a collection of statements, they should be grouped in braces.

Your example is still only one line per case, but those braces are less of a problem when amortized over more lines (note that there are extra braces enforced by the `if` and `else`):

switch x {
case 0 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}

case 1 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(1)
    }
}

case 2 {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(2)
    }
}

default {
    //a comment or two describing what's happening in this particular case
    //because commenting is good practice
    result=runSomeCode()
    if result {
        //do something here
    }
    else {
        //maybe some more stuff
        print(0)
    }
}
}

On Jul 7, 2016, at 13:24 , Brandon Knope <bknope@me.com <mailto:bknope@me.com>> wrote:

When each case only takes up one line, it may look nice and concise. But what happens in the common case when your case takes up more lines and you indent your braces?

switch x {
case 0 { print(0) }
case 1 { print(1) }
case 2 { print(2) }
default { print("other”) }
}

switch x {
case 0 {
    print(0)
}
case 1 {
    print(1)
}
case 2 {
    print(2)
}
default {
    print("other”)
}
}

I think this looks much heavier and harder to read. All the braces detract from the important stuff

Brandon

The colon syntax evokes a label, but the modern, complex `case` statements in Swift don’t act much like labels.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #17

> Fallthrough ceases to make much sense with braces, and it is a handy
> feature of switch statements every so often.
>
I assume you mean "Fallthrough cases make much 'less' sense with braces"?

Haha, more or less, yup.

···

On Thu, Jul 7, 2016 at 3:41 PM, Roth Michaels via swift-evolution < swift-evolution@swift.org> wrote:

On Thu, Jul 07 2016 at 04:33:17 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

--
Roth Michaels
roth@rothmichaels.us

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Roth Michaels) #18

I assume you mean "Fallthrough cases make much 'less' sense with braces"?

···

On Thu, Jul 07 2016 at 04:33:17 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Fallthrough ceases to make much sense with braces, and it is a handy
feature of switch statements every so often.

--
Roth Michaels
roth@rothmichaels.us


(Taras Zakharko) #19

I always wrap my case blocks in curly braces. Personally, I agree with G.B. that the switch syntax seems inconsistent at best. While there are labels and limited form of goto in Swift, case labels don’t act anything like that. I’d prefer symmetry with if by having obligatory braces.

— Taras