question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: tuple-friendly return type syntax for methods

See original GitHub issue

(taken from NH discussion here: https://news.ycombinator.com/item?id=12361949)

The tuple syntax (#347), while straightforward on its own, is rather distracting in method declarations. E.g. here:

public (int sum, int count) Tally(IEnumerable<int> values)

The name of the method gets “squished” between the return type and the parameter list, even though it’s more important than either when scanning code.

I suggest adding some kind of syntax where the return type follows the parameter list to avoid this problem. There is a precedent for it in a C-style language with traditional declarators, albeit in somewhat different circumstances - C++11 has added the return-type-at-end syntax auto f(...) -> T.

Because -> is already used in C#, and because it is too easily confused with => for lambdas and expression-bodies methods, I don’t think C++11 syntax is a good fit. Instead, suggestion is to take the syntax from Ada by reusing return:

public Tally(IEnumerable<int> values) return (int sum, int count) { ... }

or

public Tally(IEnumerable<int> values) return (int sum, int count) =>

This makes method name the first identifier on the line, inputs next, and finally outputs, matching the natural reading flow (“Tally takes values and returns their sum and count”). It’s also more consistent with Func<TArg, ..., TResult>.

Grammar-wise, it looks like it’s a very straightforward extension on the existing constructor syntax. Basically things that would be parsed as constructors and then rejected because the identifier didn’t match the class, would now become methods. Whether to require return, or to imply void in its absence, is largely a matter of taste. And, obviously, return is already a keyword, and it cannot appear in this position today, so this is fully backwards compatible.

I don’t suggest applying return to anything other than the methods and delegates (in particular, not to properties). Tuple types are much less of an issue there from readability perspective because there’s no argument list, and thus the name of the property is always in a prominent position at the end of the line, whereas the use of return would be confusing for properties with setters:

public (int sum, int count) Totals {
  get => ...
  set => ...
}

While the main motivation is for tuples, there are other circumstances where this is useful. One is any other case where the return type is complicated - for example, a gnarly nested generic:

Task<Dictionary<string, Func<bool>> Foo(object x) => ...

// becomes

Foo(object x) return Task<Dictionary<string, Func<bool>> => ...

Another is when the method itself is generic - as most C# devs know, Intellisense gets in the way when typing out something like:

public T Foo<T>()

because when you get to the first T, it’s not declared yet, and so Intellisense suggests other identifiers in scope that happen to start with a T; you have to explicitly close the completion list to get it out of the way, and if you forget, it’ll probably substitute something else when you press space after T. On the other hand, with the return syntax:

public Foo<T>() return T

Usage follows declaration for T, and so you would get proper completion for it in Intellisense by the time you get past return.

There’s also a marginal benefit in that this syntax permits a more natural way to apply attributes to the return value:

[return: Foo]
int Bar();

// becomes

int Bar() return [Foo] int;

Side note: this presupposes that there’s no plan to add a generic form of type-follows-name declarators to C# that would apply everywhere (akin to x: T form used by TypeScript and many other languages). If there is such a plan, this is redundant, and return is a poor choice, because it couldn’t be used uniformly for non-method entities with types.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:12
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
alrzcommented, Sep 14, 2016

By the way, I think -> is a good fit since it is used in C++ for the same purpose(s) and is familiar.

public F() -> (int, int) => (1,2); // I smell Haskell

Then it can be considered for lambda expressions to explicitly specify return type.

M(x -> string => x.Name);

However, a third-person returns is still a good candidate because we have where in the same position.

public F<T>() returns (in, int) where T : struct => (1, 2);

Not sure if this should be permitted only for tuple types.

0reactions
CyrusNajmabadicommented, Nov 8, 2022

Closing this out. We’re doing all language design now at dotnet/csharplang. If you’re still interested in this idea let us know and we can migrate this over to a discussion in that repo. Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Proposal: Trailing return type #8448 - dotnet/roslyn
PS: I'm not proposing return type inference, so presence of auto or var ... Proposal: tuple-friendly return type syntax for methods #13744.
Read more >
private method as trailing return type (decltype) - c++
This is unrelated to both private and trailing return types. The problem here is that while all declared names in a class are...
Read more >
Proposal to remove procedure syntax
is going to be dropped in Scala 3, where you will need to write the following instead: def f() = { ... }...
Read more >
PHP RFC: Return Type Declarations
This proposal adds an optional return type declaration to function declarations including closures, functions, generators, and methods. This RFC ...
Read more >
Returning a Value from a Method (The Java™ Tutorials ...
You declare a method's return type in its method declaration. Within the body of the method, you use the return statement to return...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found