[Accepted] SE-0284: Allow Multiple Variadic Parameters in Functions, Subscripts, and Initializers

The review of SE-0284 has concluded.

Some reviewers indicated that they would prefer to format code in certain ways to aid with legibility, but the functionality itself was well received. The core team noted that this was an oversight in the original implementation and should have been permitted in the original implementation.

As such, SE-0284 is accepted.

Thank you to everyone who participated in this review.

Saleem Abdulrasool
Review Manager

18 Likes

Presumably, this is referring to the concern I raised about ambiguity and formatting. I want to clarify what that comment is claiming:

Claim 1: The examples given in the proposal's text itself make a case for not accepting the proposal because they make understanding the call-site for assertArgs more difficult. Could this potentially be fixed by formatting in a particular way, say by breaking a small line (less than 80 columns) into multiple lines? Sure. Is that what we want to actually do in practice? I don't think that's going to happen. (Maybe it is; I'd be happy to be proven wrong.)

Claim 2: For a non-semantic code formatter, it can either (a) format multiple variadic parameters properly with extra indentation for trailing arguments XOR (b) it can properly format an unlabeled argument following a labeled argument. (Tony's comment below confirms that swift-format operates on syntax without requiring name resolution). So either we accept that (a) existing code with long invocations relying on unlabeled arguments following labeled arguments gets misformatted XOR (b) new code with long invocations relying on multiple variadic parameters gets misformatted. Neither of these are appealing.

I'm a bit surprised that I did not receive any response from the review manager or the proposal authors. I have two questions here:

  1. Are my concerns unreasonable/unfalsifiable? Are the review manager + proposal author(s) expected to respond to all concerns raised during review?
  2. Let's say we adopt the formatting rule to add indentation (option (a)), which makes the multiple variadic parameters case work. Now, call-sites using APIs with unlabeled parameters following labeled parameters might get mis-formatted... Whose responsibility is it to check how widespread this regression might be in practice? Is it the responsibility of the person who raised the concern? The review manager's? The proposal authors'?
2 Likes

@typesanitizer Reading back over your comment now, I can't identify any part of the critique that isn't more generally applicable to having variadic parameters in non-primary positions. E.g., with regards to assertArgs you say:

But an alternate version of the API could be written (without SE-0284) as:

try assertArgs(["swift", "-foo", "-bar"], parseTo: .interactive, leaving: "-foo", "-bar")

The same goes for the addSubviews example. Perhaps the "after" versions are not the best examples of APIs that could be helped with this proposal, but AFAICT your comment would be more applicable as an argument against adopting those specific APIs (and could perhaps apply to a more general pattern of APIs which might use SE-0284).

IMO, this is unfeasible as a general policy. We certainly can't force proposal authors to respond to every concern, nor does it seem reasonable to me to reject an otherwise-sound proposal on the grounds that an author did not respond to some comment. It's the job of the Core Team to synthesize all the feedback a review generates and make a decision, and they are capable of doing that whether or not every comment has a response.

Of course, if someone raises a concern in a review thread, by not responding the proposal author is foregoing their last opportunity to convince the Core Team that the concern need not be (or already is) addressed by the proposal—but ultimately, that's their prerogative.

ETA: We do currently have this note as part of the Swift Evolution Process document:

To avoid delays, it is important that the proposal authors be available to answer questions, address feedback, and clarify their intent during the review period.

This sort of 'soft' expectation is about as strict as I'd like things to be, officially.

2 Likes

Sorry for not responding to your concerns during the review period.

Personally, I don't think we should adopt new formatting rules to improve varargs formatting at the expense of formatting non-variadic argument lists. To some extent, these formatting issues already existed pre-SE-0284, so in my opinion the proposal doesn't introduce a significant regression. For example, func addSubview(_ view: UIView, constraints: NSLayoutConstraint...) seems equally difficult to automatically format when compared to the version with 2 variadic params. I'd also argue that variadic functions are more likely to be manually formatted because they're designed to give the programmer more stylistic flexibility when writing arguments at the call site, in exchange for a loss of clarity if they're misused. That's not to say your concerns are invalid or unreasonable, but I think the benefits outweigh them in this case.

I'm not sure I have a great answer to your process questions, but IMO as the proposal author I could've handled this part of the review better.

1 Like

Sure. I don't see how that is a problem with the critique. I'm pointing out what in my view is a code anti-pattern, and the fact that the proposal uses the same kinds of examples in a positive light means that I'm less inclined to support the proposal.

One of the reasons to have examples (and the discussion!) is to convince the reviewers that the feature can be used to create good APIs. Most features come with some downsides too, and that's understood. What I'm saying is that the examples given in the proposal are not doing a good job of convincing one how this feature enables people to write APIs that do not impose an additional understanding burden at the call-site. A feature cannot (and IMO should not) be evaluated based on examples that are not part of the proposal or discussion. If someone has a positive example, they should bring it up, so as to strengthen the proposal. If someone has a negative example, they should still bring it up, to highlight the proposal's weaknesses.

You'll notice that I didn't give a -1 to the proposal. That's very deliberate, because I hadn't made up my mind. I was, and am open to being convinced by better examples.


Ok that's fair, at least now I understand where you stand on the point raised. I disagree on the "significant" bit, but that's subjective, so I don't want to dwell on that.

IMO this is a non-starter for many projects; in other language communities (esp. Go, Elm and to some extent Rust), I've definitely seen places with "everything goes through the formatter, no questions asked, no tweaking by hand". That said, I don't know what % of folks in the Swift community feel this way, so I'm happy to give you the benefit of doubt here, y'all almost certainly write a lot more Swift code than I do. :sweat_smile:

That's fair. Based on the given examples, I disagree with you and the core team on the cost/benefit here, but it is what it is. We don't need to agree on everything. :slight_smile:

2 Likes

Yeah, your points are all valid, and I didn't mean to imply that your critique was wrong so much as illustrate why it might not have seemed like the most urgent concern to address. It points out what might be some weak examples, but it doesn't strike at the 'core' of the motivation for the proposal, IMO.

That's quite the can of worms. :slight_smile: These two threads from last year dealt with exactly that issue, and they were, as far as I can remember, the most contentious threads of the year.

Thanks for pointing these out. I joined in ~July, so I wasn't aware of these discussions.

1 Like

Since (as has been pointed out) the issues you raise with formatting also apply to unlabeled parameters after labeled ones, it's possible that we might want to format that differently anyway. That is, we may decide that the right (narrow) formatting for foo(bar: x, baz: y, z) is

foo(
  bar: x,
  baz: y, z)

regardless of whether 'baz' is variadic vs. followed by an unlabeled parameter.

1 Like

Some of us might want to “align the colons” and format it like this:

foo(
  bar: x,
  baz: y,
       z
)
1 Like

Yeah, my point wasn't "this is a good formatting" but "in the discussions about formatting, it may not be a variadic vs. non-variadic choice after all".

4 Likes