SE-0257: Eliding commas from multiline expression lists

• What is your evaluation of the proposal?

-1

I understand the analogy between optional semicolons and optional commas, but it seems to me that semicolons are optional because statements are normally written on separate lines. It's convenient to use semicolons occasionally, when grouping short statements on the same line (e.g. in a one-line function definition), but that's an occasional usage.

With commas, the situation is reversed. Multiple expressions are normally written on the same line, and commas are needed as separators. Having a rule that says they can be omitted if the expressions are written on separate lines creates code that I find harder to read. I have to mentally add commas where they're not written.

I don’t think it’s helped by the fact that I also have to learn a set of exceptions where I shouldn’t (mentally) add commas.

I'd much rather have trailing commas!

• How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading of the proposal. I’ve also been following the discussion.

2 Likes

I've moved from reluctantly +1 to reluctantly -1, because of the implications of the following:

  • I have not seen or managed to come up with a single example where a semicolon is necessary at the end of a line. (good)

  • I have seen and can come up with lots of examples where a comma will be necessary at the end of a line. (not so good)

Or put differently:

  • A semicolon at the end of a line is never needed.

  • A comma at the end of a line will sometimes be needed.


The above makes comma elision (as proposed) much more complex and confusing than semicolon elision (as can be seen from much of the discussion here).

However, note that comma elision would be exactly as straight forward as semicolon elision if we restricted it so that it was "only" allowed for:

  • dictionary literals
  • fully-labeled argument lists
  • parameter lists (unlabeled params still have eg _ arg: so they're ok)
  • fully-labeled tuples

That is, comma elision would only be allowed in contexts where commas are truly redundant (the labels/keys and colon makes them so), and (afaics) this way all commas could be elided without ambiguities, not only the ones at the end of a line.

Since the label/key and colon is effectively, well not strictly a separator, but rather a "bullet point" or introduction to each item, perhaps array literals and other un- or partially labeled constructs could be allowed provided they too used an item-introducing colon even for the unlabeled items:

let a: [SomeEnum] = [
  _: .foo
         .bar
  _: .bar
  _: .foo.bar.foo
         .bar.foo.bar
  _: foo _: foo.bar _: foo
]

print(
    _: "Hello"
    _: "world"
    separator: ", " // ;-)
    terminator: "!\n"
)

func dividingClosed(
    _ other: Polycurve
    straightIntersections: Bool = false
    threshold: Float = 1/64
) -> (
    inside: [Polycurve]
    outside: [Polycurve]
    intersections: [Float]
)
{
    ...
}

let package = Package(
    name: "Paper"
    products: [
        _: .executable(name: "tool" targets: ["tool"])
        _: .library(name: "Paper" targets: ["Paper"])
    ...

(No, the _: is not pretty, I agree, it's just a first attempt to come up with something that makes my envisioned more consistent comma elision work also for unlabeled constructs.)

Thanks for calling this out here. The proposed change does only cover the elision of commas from expression lists, not all comma separated lists.

Speaking personally, that sounds like a reasonable modification for the core team to consider.

1 Like

I agree with this as well. It would be my preference to see all comma-separated lists treated consistently throughout the language.

Problem is, that all comma separated lists throughout the language are not equally possible to treat consistently.

As mentioned above, the only ones that can be unambiguously treated are those whose items are reduntantly comma separated, ie the ones in which each item is preceded by a (label/key and) colon.

Let's not build strawmen. I am not making the claim that elision in one place implies we should allow it everywhere. I am drawing an analogy between one form of separator punctuation and another and using human experience with one form to consider how humans will react in the presence of the other form.

I'm not sure what you mean by simple vs complete signatures. I was referring to complex expressions that rely on operator precedence (potentially of user-defined operators and precedences). It is possible to write expressions that are quite difficult for humans to parse accurately due to parentheses elision and this is not a problem - humans are quite capable of exercising good judgement about when parentheses are necessary for readable code. We are quite capable of learning to apply the same kind of judgment with regard to comma elision.

You misunderstand what I mean. I mean that I think the language should apply consistent rules related to comma elision everywhere comma-separated lists occur. I don't mean that elision should be required everywhere or applied indiscriminately. I think I have made that point abundantly clear several times now.

I know perfectly well what you meant. I think you might have misunderstood what I meant though ; ), see my previous post that I referred to.

I think the objection that many people have, and which I share, is that issues with and exceptions to existing elision rules (parentheses, semicolons, whatever) are generally encountered in fairly pathological cases. OTOH, it seems like heavy users of comma elision will likely run into one of these exceptions in practice, since the exceptions arise from pretty commonly used constructs like enum cases and static members.

I'll also echo @Chris_Lattner3's desire for some kind of data about how much existing code could make use of this feature without running into any of the exceptions that have been discussed.

6 Likes

That is an interesting approach, but I would still prefer to see the same rules applied to all comma separate lists in the language. As with parentheses, I think programmers are quite capable of learning when commas are necessary for clarity and correctness. The rule you advocate would ban some great use cases for this proposal and introduce undesirable (IMO) special cases into the language rules.

Isn’t this exchange actually a perfect example how this change introduces confusion? You suddenly can’t tell anymore at a glance whether the expression runs on or not.

There was another snippet posted which I started at and had a hard time parsing. That’s when I realised that commas serve as delimiters for my visual parsing in ways line breaks often don’t.

Yes, the counter argument is that I can still use commas but I’m not only reading my own code.

And I wonder if I’d start questioning expressions broken up across lines because it could perhaps also be a list with comma elision - even in my own code. God knows I often can’t remember if I’ve written it or a colleague...

2 Likes

Well, with something like the attempt I made (in the last part of the post) to include all comma separated lists, the rules would be simpler than with the current proposal, since there'd be no ambiguities, or even need for commas, they'd be a purely aesthetic choice. The _: (of my said attempt) is arguably worse than a few unavoidable comma separated lists here and there though, but it's much more consistent.

I think comma separated lists might be even worse if they are here and there instead of simply everywhere. We'd probably find ourselves thinking way too much about why/if some particular list really must have commas, or how we might possibly get rid of them, or get a bit disappointed that we really do have to add commas because we have to edit an item in a way which makes them necessary.

Nobody complains about needing to use parentheses to write (a + b) * c or thinks we should require parentheses everywhere for consistency. IMO commas under this proposal fall into a very similar category. It’s ok if you and others have a different opinion about this. The core team has a tough decision to make!

This just introduces a new kind of inconsistency. Now _: is sometimes necessary and sometimes not - i.e. it is required for multiline lists without commas when there is no label otherwise required. I think the rules are simpler if we just allow comma elision and rely on users to develop good judgement about when to use commas to pre-empt any potential confusion just as we do with parentheses in expressions where operator precedence requires it (or where we don’t want to rely on readers to understand precedence).

2 Likes
  • What is your evaluation of the proposal?
    -1

  • Is the problem being addressed significant enough to warrant a change to Swift?
    No. This proposal introduces visual ambiguity without improving the use of the language in any meaningful way. A comma is visually lightweight, not some kind of burden on readability, and in my opinion helps improve readability.

    A lot of people who are in favour of this proposal seem to want it because they want the flexibility of moving around parameters in a function, which is hampered by disallowing trailing commas.

    If that is such a big concern, a better alternative would be to allow trailing commas, like so:

var result = foo(
    bar,
    baz,
)
  • Does this proposal fit well with the feel and direction of Swift?
    No.

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
    N/A

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    Read through the proposal and looked through a handful of comments.

… or where we have no choice but to use commas, even though we didn't want to or think we had to, as in:

let package = Package(
    name: "Paper"
    products: [
        .executable(name: "tool", targets: ["tool"]), // :´(
        .library(name: "Paper", targets: ["Paper"]), // :´(

This is a good example of how comma elision (as currently proposed) isn't nearly as nice as I first thought it would be. I saw your reaction to this before and I agree to leave it to the core team.

(EDIT: Removed a misquote)

3 Likes

I think this is the part where I disagree. They don't feel like a similar category to me. Parens group logical chunks of thought or priority. Commas separate between members of a group of some sort.

So in spite of the fact that both can be omitted, and also semicolons, commas are in a different usage group for me.

5 Likes

Channeling many other people on this list:

  • I would love to see the proposal explain why it is only removing some commas from the language, and not in other places (tuple exprs, argument lists, etc). Even if it chooses not to propose this, it seems reasonable to list it in 'alternatives considered' with rationale.

  • It is repeatedly stated that some vague quality of improvement work will be done to generate diagnostics, but that work is not part of the implementation provided with the proposal. If we are to evaluate this in totality, then that seems like it should be included.

-Chris

11 Likes

-1 for this proposal. It seems to me that Swift would seem more complicated and less new-user-friendly if this proposal is incorporated into the language. Using explicit commas to separate parameters is more readable too.

What is your evaluation of the proposal?

Strong -1.

Is the problem being addressed significant enough to warrant a change to Swift?

Absolutely no. I have never felt the need to use fewer commas, nor have I heard anyone else complain about it.

Does this proposal fit well with the feel and direction of Swift?

No. I feel it compromises two core values of Swift: clarity because the distinction between what's a plain instruction and what's an element of a list would no longer be obvious and safety because of the confusion and mistakes caused by the lack of clarity.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

Not even Python or Ruby, languages (in)famous for their "convenience over strictness", have this.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read the proposal and most of the thread.

1 Like

It is worth considering (I mention this, because it has been brought up in a previous comment) that no, Ruby, does not have comma-less parameter lists or array / hash literals. It does however have syntax shortcuts like the following:

%w(first second third) == ["first", "second", "third"]
%i(first second third) == [:first, :second, :third] # list of symbols

and a couple of similar shortcuts.

However, these are of a very different nature. Regardless of whether one believes that the complexity added is worth the benefit, at least one can argue that allowing people to omit commas and quotes (for strings) or colons (for symbols) has tangible benefits especially for people using Ruby for e.g. scripting; it just saves a lot of keystrokes. Furthermore, the scope of these declarations are very limited: it's immediately obvious that this special syntax will only apply within the scope of the %w()/%i() construction, so there should be no ambiguities.

By contrast, I simply do not see how a single comma between arguments / array elements makes a huge difference in terms of readability and I've certainly never considered it to be a "pain" in any way, no matter how DSL-y my code looks like. If anything, I would support special sugar for more specialised cases as in Ruby where the benefit is more striking and the context of this sugar is limited in scope.

Even if it didn't have any obvious downsides, I fail to see how this proposal is in any way addressing an actual problem within the Swift language (as opposed to some extremely subjective ideal about "code beauty"). The only argument I can see that I would personally attach any value to is the "minimizing diffs" one, but a) this could also be mitigated by allowing trailing commas (as mentioned several times) and b) let's be honest, git is a great tool and probably the best we have, but it kind of sucks at diffs anyway, because it has zero semantic information about the programming language, and there are 200 other things I wish git could indicate to me in a better way (e.g. when a method has been extracted) that routinely cause confusion in code reviews, that this minor nuisance is just really not that bad.

This coupled with the fact that it can cause real problems in some cases e.g. involving operators on the next line etc.—which might not be a "problem" for the compiler but certainly can be one for developers who might fail to understand the error messages—leads me to think that this feature does not fit in with the direction of Swift and would be a bad addition.

1 Like