Func return elision and subjective feedback

I understand the review is over, but I’d like to address this point.

It is evident from the review thread that a substantial number of people see an important difference between functions and property getters, even if no one was quite able to put into words the nature of that difference.

To the best of my understanding, it essentially boils down to the review question:

That is obviously a subjective question, and its answers will be subjective as well, but it is nevertheless part of the review template so I don’t think it’s fair to brush off these concerns out of hand.

I’m not sure I can sufficiently explain the reasoning, but I will do my best:

A func declaration creates a subroutine, which can be called from other code. That other code, at the call site, expects a value to be returned (we’re talking non-void functions here). Therefore the function body should contain a return statement to match expectations. If there is no return, then there is an impedance mismatch between the definition and use of the function.

On the other hand, a computed property does not “feel like” a subroutine. Even if it is implemented as a function call under the hood, at the use-site it looks and feels like a property access. Indeed, the mere fact that Swift supports computed properties at all, rather than making people use bona fide functions instead, shows that the designers of the language recognize the importance of this distinction.

When the code block defining a computed property is just a single line—especially when it is on the same line as the property declaration itself—people don’t think of it as a function at all. They see it as describing a value, rather than defining a subroutine.

I know that might sound like splitting hairs, but again, many people in the review thread see the difference as real, and the very existence of computed properties indicates that the creators of Swift understand the distinction as well.

• • •

It is similar with in-line closures. In something like students.map{ $0.name }, the part in curly braces doesn’t *feel* like a function. Yes, it *is* a function, but people don’t think of it that way. They think of it as describing a value.

It would be an impedance mismatch to require return in such a closure, because people don’t think of it as a function. Readers would have to stop and think, “Wait, what is this returning from? Is the enclosing function returning now? No, it can’t be that, let’s see… ah right, the trailing closure is technically a function, so the return is really just local to that closure and doesn’t actually do anything here.”

Along the same lines, with a computed property the currently-required return tends to make people pause and go, “Why is there a return here? We’re not inside a function, this is the body of a struct. Oh… yeah… the computed property getter is technically a function.”

• • •

Essentially, we have a large number of people stating in the review thread that they believe omitting return from a single-expression computed property definition *does* fit the feel and direction of Swift, whereas omitting return from a single-expression func declaration does *not* fit the feel and direction of Swift.

As far as I can tell, this is because func declarations look and feel like functions—which get called as subroutines—so whenever they return a value to the caller they should say that they are doing so with a return statement. Conversely, computed properties look and feel like property accesses, so a return statement seems entirely out of place.

It is a matter of “the feel and direction of Swift”, and we saw many people in the review thread expressing the same opinion on this matter. It is no surprise that these opinions did not include a rigorous logical derivation of their position: they are opinions, answering a subjective question, which specifically asks about the “feel” of the language.

13 Likes

This is really unfair, Nevin. You're insinuating that the core team* didn't understand the feedback that was against applying this to all functions, and then writing a very long post and thereby asking them to put in more effort to read your arguments, which have already been made. I'm not saying decisions can't be revisited, but there's pretty much no reason to revisit them immediately after acceptance, because there's no new information provided.

Some proposals don't come out the way we like. That's the core team's perogative, and ultimately a fact about any controversial decision that includes community input. There's no language that only has features you like except the one you design yourself.

* reminder that I'm an Apple person but not on the core team, and also that I would have preferred accessors-only myself.

15 Likes

He's merely attempting to reply to the "no strong argument" conclusion made in the acceptance summary. I certainly didn't read any insinuations. At worst it's a reaction to the closed nature of core team discussions and a decision which seems to (at least partly) go against the majority. I think it also exposes an interesting dichotomy: the core team wanted a "strong case" to be made, yet the reaction was largely from the "feel and direction" section. It would seem rather difficult to make such a case when asked a rather subjective question. Frankly, the fact that many reviewers felt that the inconsistency that was apparently the deciding factor here better matched the "look and feel" of Swift was very interesting. It's also rather unclear to me what kind of strong arguments the core team is looking for in that section.

Depending on how the release schedules work out, there may be no other time for things to be revisited. There is no "Evolving" stage for language features, and in the age of source and ABI stability, once features are shipped, they have to stay shipped, barring the rather nebulous and increasingly rare standard of "active harm". So there seems to be little opportunity to provide the new information you're asking for, at least for those of us who aren't involved in the day to day development of Swift.

I think we all accept that. I just think Nevin is wondering, like we all have at some point, if it was possible to better impact a review and push it towards the resolution we wanted. Would his argument have been strong enough? Should we all try to make stronger arguments whenever we disagree with a proposal to ensure they're heard?

I also wonder, what are these post-review threads for, if not to express what we think may have been missed?

5 Likes

These threads are announcements of the outcome. Sometimes process questions or outcome clarifications are raised and discussed. They should definitely not become relitigation threads.There is a reason we lock review threads, and that reason isn’t to move the discussion to a new thread on Evolution Announcements.

Nevin's post is tricky because it is both process and relitigation. So I’m moving these comments to Evolution Discussion, because that's the right place for continued discussion of why people dislike func-specific return elision.

edit: to make this post make more sense now it's in the discussion topic :slight_smile:

9 Likes

I don't think talking about majorities makes sense in Swift evolution. The people contributing with their opinion are not representative in any way, they only provide feedback. And their feedback should not be viewed as voting.

11 Likes

I know it’s not voting, I was just talking about most of the reviews in the thread. Even if it’s not voting I still think it’s interesting to see decisions come down differently than the majority opinion.

This is a really important point. Swift is not a democracy,¹ and it's a fundamental mistake to operate from the assumption that it is. The core team makes the decisions, with advice from S-E. Like Jordan, I definitely don't agree with every decision that core makes, but I will happily vouch for the fact that they do listen seriously to the feedback from review threads. Ultimately, however, it's advice, and they are free to make whatever decisions they want. The best we can do as proposal authors and reviewers is to make our case as clearly as possible.

¹ it's a cheerocracy.

16 Likes

I thought the wording of the acceptance post made it clear that it's the strength of the arguments that hold the most value, and they concluded a strong enough case for excluding functions from a "single uniform rule" wasn't made.

I'd also caution against assuming the majority of opinions posted represents the majority of the opinions of readers or of the community at large. Also note that the fact a majority appears to feel a certain way isn't necessarily by itself a sufficient justification for a position. This isn't aimed at anyone in particular; it's just something to keep in mind.

2 Likes

I think the issue for me personally is that I felt the acceptance post didn't explain why this goes with the fit and feel of swift, since that seems to be the main sticking point on this issue. It might be nice to hear more details on why that was the case.

1 Like

FYI as there are many non-native English speakers here I wanted to clear this up -- the use of "elide" everywhere on this message board is incorrect. The proper word in this context is "omit."

From the Oxford American Dictionary that ships with macOS:

The standard meaning of the verb elide is ‘omit,’ most frequently used as a term to describe the way that some sounds or syllables are dropped in speech, e.g., in contractions such as I'll or he's. The result of such omission (or elision) is that the two surrounding syllables are merged; this fact has given rise to a new sense, with the meaning ‘join together, merge,’ as in the two things elided in his mind. This new sense is now common in general use.

"Elide" and "elision" show up in a handful of places in C++ terminology, which is probably how it got into these proposals, but it isn't incorrect.

7 Likes

As a general rule, the core team doesn't in its acceptance go into detail summarizing the review discussion. Where the core team accepts a proposal without amendment, the first place to look for detailed justification is the proposal itself.* I just reread the proposal and it's main thrust is "Swift does this for closures, it should do it for functions too" and that seems very much to be a "feel and direction"-based argument.

But it's reasonable to disagree with this line of argument. During the review there were cases made both for and against, along with counter-arguments. The core team weighed this input and decided. As the review acceptance said, the team felt the case made against for functions specifically were not persuasive enough to amend the proposal to exclude them, whereas the case for a single uniform rule was enough to accept as proposed. I'd suggest a re-read of the review thread for more background on this.

* If the team felt the case made in the proposal was flawed, but accepted it anyway for other reasons, we'd probably say so; though chances are we'd say so before or during the review and ask it be changed prior to the accept.

3 Likes

I think @Ben_Cohen is being very charitable when describing this as “process and relitigation” because the original post is clearly almost entirely relitigation. A process-focused thread about how such subjective matters are treated in the evolution process wouldn't be 600+ words re-arguing the point on this specific proposal, though it may use the proposal as one example. This thread sets a bad precedent, and I would prefer any discussion about process happen in a much more neutral thread so it isn't seen as endorsing wasting everyone's time in this way.

Ultimately I think the issue comes down to whether it's really possible to have stronger or weaker arguments for "look and feel" most of the time. Really strong or weak arguments here only seem possible at the extremes, not when splitting a very fine hair as we saw here. So when the core team's conclusion said that the decision was due to the strength of arguments, it was somewhat surprising, given the largely subjective nature of the discussion. Perhaps it wouldn't have gotten the reaction it did if the decision had been expressed not in terms of strength of argument but the core team ultimately agreeing with one one type of consistency over the other it would've been more clear why the decision was made.

1 Like

I think quite the opposite. It is even easier to make poor arguments when they are being made to back up subjective preferences. It is common to have an immediate reaction ("I like/hate this"), then to try and come up with some post-hoc rationalization. I certainly find myself doing this. The problem is, when there is no good justification forthcoming, it's really tempting to provide a poor one. We all like to think of ourselves as rational human beings, and it's not psychologically comfortable to realize that your preferences don't have a rational basis. So there is, I believe, a tendency towards unconscious bias in favor of weak arguments that back up your instinctive beliefs.


To push back on the claim that it is not possible to judge whether arguments are good or bad when they're about look and feel, here is a short example of what I believe is clearly a weak argument, taken from the OP.

(To be clear I am not debating the proposal acceptance, just using this as an example of how arguments about look and feel can be considered weak or unconvincing. This is also not personal: I'm just quoting this example because it's from this thread. I could have chosen one from the original thread instead. And these are just my particular opinions on a new argument made after the review, not necessarily reflective of the core team's views)

Firstly, how the call site looks is irrelevant to how you write the body of the function (or if it is relevant, why is not explained). There are some "expectations" that someone has apparently, but I'm not seeing who, or why it's important these expectations be "matched".

Second, this argument applies identically to getters, which also return a value, so why are functions different to getters (the whole point of this post)? Yes, later on there are justifications for why getters are different to functions, but they are unrelated to this point made here.

Finally, "impedance mismatch" appears to be a misuse of the term, and its use here doesn't add anything. Impedance mismatch in API design refers to inconvenience for the API user when they have to perform conversions from one kind of thing to another when relaying data between APIs, similar to how impedances might need matching between a source and a load. Much better if possible to redesign the API to make the impedances match in the first place. Here, there is no inconvenience, no need to perform extra steps, by having or not having a return in the body (again, because how the function body can be written is irrelevant to the caller).


Now, it is of course possible to respond to my critique above. And in the review thread, this happened several times. Someone would rationalize a preference, someone else would push back, and then someone else respond to the push back. This is all great. But at some point, the review comes to an end and the core team make a decision. As part of that decision, it's reasonable to say in summary that the case made for a particular alternative to the proposal just wasn't strong enough. But to say the core team cannot judge the arguments made, because they are purely subjective and all we can do is agree to disagree, does a real disservice to the process and to the people who put time into debating these points.

9 Likes

This is one of the reasons I rarely participate in SE reviews these days. The core team seem to want to have their cake and eat it - i.e. having a superficially 'open' process to lend credibility to the language, but also treating the process like a formality and not really as a mechanism to gather useful, high-quality feedback.

Sometimes we get asked for our opinions:

But then, high-impact features like property delegates move from pitch to review in less than a month, reviews only last for 7 days (is it really possible to review big changes, like how we expose opaque types, in such a short time?) and sometimes there are several important reviews going on in parallel. Many recent proposals have changed several times during the review itself, making it hard to follow what you are supposed to be considering, and some of them just punt design decisions entirely to the core team (at which point nobody has a chance to argue them).

We in the community try our best to improve the Swift language and share our experience, but under such circumstances I'm not sure how we are supposed to deliver high-quality feedback, and given the ability of Apple developers and core-team members to stretch and bend what few rules and procedures we have, it very often does not feel worth the struggle.

All of this is to the detriment of the language. How can my company realistically decide to build its new server backend using Swift? How can I argue that it's worth retraining engineers in Swift? Or that it is worth favouring hires with Swift experience, when the language changes this way?

Swift is open-source, but it increasingly feels like it is not community-driven. It is understandable that the original core team was dominated by Apple employees, but I feel that situation is increasingly becoming untenable.

Just MHO.

2 Likes

I've been following Swift Evolution from afar and I have enormous respect for the way the core team has been managing this process. The process allows for voices to be heard and I sleep comfortably knowing that the chance for oversight in any proposal is very very low as it's being bikeshed by the community. I didn't participate in the review thread aside from clicking :heart:, so I don't want this to sound like I want relitigation. However, I have a small bit of feedback regarding the acceptance of this proposal.

I agree with @spadafiva when he says:

To which @Ben_Cohen replied:

Although the proposal was accepted as is, I still think it could have used some explanation and rationale behind the decision. One reason an explanation might be useful is that this proposal itself was divisive on some topics, as the review notes suggested. I believe going back and reading it won't provide any new insight if the commenter already read and analyzed the proposal. An explanation as to why the points made in the proposal are considered to be significant enough by the core team (or why the points made against not considered significant) probably would have made those who commented against feel more included.

To sum up, my feedback is that if the community seems divided on a proposal, it would be nice to provide a rationale that weighs arguments and counter-arguments, even if the proposal is accepted as is.

This might be my first post on Swift Evolution so I want to take the chance to stress that I have the utmost respect for the core team for being such a good steward of Swift, and I want to thank them for all of their efforts, as well as the passionate community trying to guarantee a bright future for Swift.

6 Likes

I don't see the point of asking for further explanation from the core team other than to give counterarguments and re-review the proposal. In my opinion, the reasoning for including functions was sufficiently summarized in the acceptance post. For a minimal change like this, I don't think there's much more detail to offer:

[O]n reviewing the feedback, the core team does not see a strong case was made against applying it to functions as well, when weighed against the benefits of a single uniform rule.

4 Likes