Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Inconsistency between named tuples and named arguments #16862

Closed
HaloFour opened this issue Feb 1, 2017 · 7 comments
Closed

Bug: Inconsistency between named tuples and named arguments #16862

HaloFour opened this issue Feb 1, 2017 · 7 comments

Comments

@HaloFour
Copy link

HaloFour commented Feb 1, 2017

Despite sharing a common syntax the behavior of named tuples and named arguments differs in one very important respect. When you reorder elements in a named argument list the values of those arguments are transposed into the correct position of the argument list. However, tuple elements are assigned only positionally regardless of any element names. I believe that this will lead to developer confusion and difficult to diagnose logic errors.

Steps to Reproduce:

    public void M() {
        void L(string name, string email) {
            Console.WriteLine($"The email is {email}.");
        }
        
        L(email: "bob@foo.com", name: "Bob");
        
        (string name, string email) tuple = (email: "bob@foo.com", name: "Bob");
        Console.WriteLine($"The email is {tuple.email}.");
    }

Expected Behavior:

Prints:

The email is bob@foo.com.
The email is bob@foo.com.

Actual Behavior:

Prints:

The email is bob@foo.com.
The email is Bob.
@alrz
Copy link
Member

alrz commented Feb 1, 2017

Tuples are "an ordered set of elements", unlike method argument list, names do not affect the order of elements. However in (string name, string email) tuple = (email: "bob@foo.com", name: "Bob"); the compiler produces a warning as names on the rhs are ignored because that's almost certainly a bug.

@HaloFour
Copy link
Author

HaloFour commented Feb 1, 2017

@alrz

Tuples are "an ordered set of elements", unlike method argument list, names do not affect the order of elements.

Argument lists are also tuples, and also a simple ordered set of elements. The syntax is the same between argument lists and tuples in C# on purpose. Argument lists in C# were also strictly positional until named arguments allowed for transposition of those elements.

I'm not arguing that tuples should be anything other than an ordered set of elements, but languages like C# opt to allow naming the elements to improve the experience for developers. It's my opinion that the compiler can and should make use of those names to help developers make the simple mistakes. Transposition of the elements is one simple way that the compiler can do that, and it is consistent with how the compiler treats the argument list tuple.

the compiler produces a warning as names on the rhs are ignored because that's almost certainly a bug.

The compiler doesn't produce any warnings and won't until a release post C# 7.0, and only when the project enables stricter warnings via warning waves. That leaves a big gap in projects that may adopt tuples with no assistance from the compiler for avoiding extremely blatant logic errors. Third-party analyzers might fill the gap in the meantime, but that still requires a developer to know that there is a gap and to manually so something to fill it.

I hold Swift as a great example of a language the supports tuples with optional naming that ensures both a good experience for the developer while at the same time assisting the developer in avoiding the simple and common mistakes.

@alrz
Copy link
Member

alrz commented Feb 1, 2017

Argument lists are also tuples

Right, but associating (named) arguments to parameters is done via overload resolution. There is no such a thing in assignments. I suppose you're proposing exactly that - to consider names to associate tuple elements. I can see how it could be useful but it seems that C# team decided names to be insignificant.

However, there are counter-examples. e.g. you can not change element names in overrides. My impression is that they've started with totally insignificant tuple names and progressively found it counter-productive.

It'd be nice to list specific cases in which names do contribute to type equivalency.

The compiler doesn't produce any warnings and won't until a release post C# 7.0

If I'm not mistaken, it does.

@HaloFour
Copy link
Author

HaloFour commented Feb 1, 2017

@alrz

Interesting. I swear I was toying with this in TryRoslyn last night and I wasn't getting warnings even on those blatant cases, and the comments on #16825 (comment) seem to indicate that the team wouldn't have time to implement them for C# 7.0. If the warnings are going to make it in then at least some of my concerns are alleviated.

I still like the idea of transposition of tuple elements in the simpler cases and I still think that it makes the behavior of the language more consistent with itself. I'd rather the example compile without warning/error and "work correctly", as it would with named arguments. I don't expect to see that happen.

@alrz
Copy link
Member

alrz commented Feb 1, 2017

comments on #16825 (comment) seem to indicate that the team wouldn't have time to implement them for C# 7.0

Note that the warnings are on the literal element names. #14217 would detect tuple name rearrangement in target types (int a, int b) t = F();, deconstruction var (a, b) = F(); etc.

@HaloFour
Copy link
Author

HaloFour commented Feb 1, 2017

@alrz

Indeed, a lot of gaps remain. That specific warning would help producers of tuples, although I imagine most of the time the boundary would be documented with a name but the tuple literal itself wouldn't be, so it probably wouldn't come up often. I think that the warnings on the consumption of the tuple would be much more important, especially deconstruction and passing that tuple across another boundary with explicit names (e.g. field, method argument, return value).

@jcouv
Copy link
Member

jcouv commented May 28, 2017

Tuple elements are positional. So I don't think it makes sense to try and allow re-ordering.

Yes, we would like to produce warnings for re-arranging names (since that is very likely an error in the code). But we couldn't fit that in C# 7.0. Therefore it will have to wait on support for warning waves (which I will try to push in 15.6).

I'll go ahead and close this discussion. Please re-open on csharplang repo if needed.

@jcouv jcouv closed this as completed May 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants