Pitch: Implicit Returns from Single-Expression Functions

I don't see the point of adding in some new syntax (e.g. =>). There is already a precedent for this in the language, single line closures, so I don't think it's reasonable to add a whole new spelling here, especially one that seems to have no other advantages (e.g. isn't really more concise). The value of this pitch is making things more uniform, and I would personally appreciate that because I've unthinkingly expected things to work this way for computed properties and instance methods many times, and then had to go back and add a return.

3 Likes

We'd also have massive trouble taking => back from being an operator (or trying to disambiguate whether it's an operator in a particular context or not).

3 Likes

The current pitch already has to make some of these trade offs and disambiguations when it comes to overloading. I found it incredibly satisafing being able to lift a lambda from JS and paste into c#.

I think => as a custom operator is bug similarly to how $ was an operator. I’d be happy to put together a pitch and push a review to diagnose and reserve for future use since => could also be used for other things like switch expressions, pure functions, etc.

1 Like

Certainly it's important to acknowledge prior work in this area; I'm sure @nate_chandler will include such a reference. Sorry your work here was missed :(

It's not great for something to get shelved for a long time and then eventually come back, but it's an evolving language and an evolving process. We had a lot more "holes" to fill in back in the pre-Swift 4 time frame... for example, that's when the generics system was getting associated type where clauses, generic subscripts, recursive constraints; key paths and Codable were making their way through the process. Major foundational pieces that we depend on everywhere in Swift today. So I agree with Chris's assessment back then, but things evolve, and Core Team members don't always agree on everything either :)

Doug

11 Likes

I’m strongly against this for the same reasons Chris Lattner opposed the first proposal for this.

This is complexity added simply to make things prettier. That does not improve readability in this case IMHO.

Swift is supposed to be beginner friendly and any beginner that comes across a function that returns a value but never has a line in which the return occurs is bound to be confused, if not frustrated.

This does not add value in my opinion, and only serves to confuse the syntax.

Simplicity yes, but also consistency. As I mentioned before, we can implicitly return from closures already.

Yes, closures are certainly a special case. If you browse topics about closures you can see they’re often avoided by beginners due to their complexity. At least with closures, you’re aware you’re in a special case and different rules apply.

Functions that sometimes have return statements and sometimes don’t depending on whose code you’re looking at is an extreme complexity burden to bear for the proposed benefit and actually reduces consistency of the language overall IMO.

Yes, closures are certainly a special case.

Functions are closures.

If you browse topics about closures you can see they’re often avoided by beginners due to their complexity. At least with closures, you’re aware you’re in a special case and different rules apply.

Could it be that looking at closures as a “special case” contributes to the avoidance?

Functions that sometimes have return statements and sometimes don’t depending on whose code you’re looking at is an extreme complexity burden to bear for the proposed benefit and actually reduces consistency of the language overall IMO.

I hear you…

I am still not convinced that adding the ability to implicitly return would introduce “extremely complex burden to bear”. Perhaps unusual in the beginning, sure, but like the iPhone’s X notch, engineers will get used to it.

Cheers!

I see the complexity burden in the context of the proposed benefit. There’s a comparatively large complexity for the small benefit of having implicit returns (the benefit being that some people can have syntactic sugar that fits their style preference).

Closures are definitely a special case of functions. I don’t think there’s any argument there. They may be functions themselves, but they’re certainly different and take time to learn. The App Development with Swift book even calls out their complexity and dedicates an entire chapter to them which starts with:

“Closures can be a complicated topic for new developers,...”

Excerpt From
App Development with Swift
Apple Education
https://itunes.apple.com/us/book/app-development-with-swift/id1219117996?mt=11
This material may be protected by copyright.

I think what @David_Keck was getting at is that closures are a very special case from the standpoint of syntax. There's a large amount of value in having closures be as terse as possible, since they are frequently used in compositional positions (e.g. .filter { $0.isIncluded } .map { $0.property }) and are expressions, not declarations. If we were in a position where the implicit return from closures had never existed, there would be a much stronger argument for introducing it for closures alone than for all single expression function-like declarations/expressions. The argument for single expression implicit returns from func declarations, as best I can tell, amounts to "typing the return is inconvenient.

I don't believe that this meets the bar for "actively harmful," and discussing possible mistaken overloads etc. does not really convince me. Does anyone have examples in the wild of actual issues arising from the lack of implicit returns from func declarations, such as StackOverflow posts about why (e.g.) bad() -> Never is being called and not bad(value: Int = 0) -> Int? "Consistency" is a vague term that deserves more qualification. There are lots of things that are inconsistent between closures and function-like decls. Why is this particular syntactic difference worth changing to make them more "consistent"?

To give a ridiculous example, why not eliminate func entirely and declare all functions as let foo = { (x: Int, y: Int) in x + y }? Obviously this is not a serious suggestion, but it illustrates the point that consistency is just one axis in a host of tradeoffs that should be considered.

4 Likes

I would like implicit return for single-expression getters of read-only properties and read-only subscripts. These getters are often trivial and Swift already allows omitting get { and } from them. The return keyword is just noise in such case.

I don't particularly like implicit return for func functions or inits.

3 Likes

@Jumhyn Very good point on declarations vs expressions. And you’re right that my meaning was that closures are special syntactically.

Your thought experiment about dropping func illustrates that having these keywords in place are important because of the readability improvements they provide, return included.

2 Likes

Lets not forget that closure syntax promotes the declaration at the point of use, hence the terseness, as oppose to function declaration.

2 Likes