Replies: 138 comments
-
Previous discussion: #4458. |
Beta Was this translation helpful? Give feedback.
-
I feel that the breaking changes that would be introduced by adopting this proposal on its own fall into three categories:
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@svick While I am only proposing removing name lookup and |
Beta Was this translation helpful? Give feedback.
-
that is entirely dependent on the compiler implementation, but new language versions are always allowed to break analyzers. Consider when expression-bodied-members were added. If you previously assumed (not unreasonably) in your analyzer that all methods with a body contained a block syntax you were broken since now the body could just be an arrow expression. |
Beta Was this translation helpful? Give feedback.
-
See: #4466 Conflating the two was always going to create a lot of confusion, and the parser that get's broken/confused the most is the human parser. |
Beta Was this translation helpful? Give feedback.
-
I've switched my position on #1064 (disallowing Maybe soft-deprecating by adding a new compiler warning in C# 10 that tells you that I agree with @HaloFour. I think the human parser should be the most important factor. While unlikely, the possibility of code like this should make us uneasy: public class Foo
{
private int _;
// Doing something important in some other file that is affected by reading Foo.WrappedValue?
public int WrappedValue => _;
public bool IsNumber(string input)
{
return double.TryParse(input, out _); // oops!
}
} (stolen from http://gafter.blogspot.com/2017/06/making-new-language-features-stand-out.html?showComment=1509474504510#c7458806139970524286) |
Beta Was this translation helpful? Give feedback.
-
I hope this proposal goes nowhere. I like the underscore usage because it makes the code less boring. As a writer, I like to use dashes, colons, semicolons, and etc to make my writing more interesting just like an _ makes the code more interesting, though it's rarely used. I want C# to be an intermediate-level language and developers having trouble with var and etc, they should look at Lua or etc. |
Beta Was this translation helpful? Give feedback.
-
Java, which is used by a larger (and some would argue more resistant to change) community seemingly has had little/no issue with the language deprecating and then disallowing the use of I've been pretty outspoken against the use of |
Beta Was this translation helpful? Give feedback.
-
My views are basically the same as @HaloFour 's. I think semantically contextual keywords make a lot of sense in theory but add developer complexity and overhead for little benefit. |
Beta Was this translation helpful? Give feedback.
-
I think this is very debatable. Consider the work we're doing to support |
Beta Was this translation helpful? Give feedback.
-
For clarification: this proposal explicitly states that cases like this should keep working as they do, contextual keywords will always exist. Just because properties use the
I totally agree that there is not engineering reason to change this. It just works for the compiler folks (as far as I am aware). But I think it add an unnecessary burden on programmers using the language. Things like Every other language I've encounterd (C++, Jave, Typescript, Pytho, Go) does not use name lookup rules to determine whether something is a keyword (including F# and Visual Basic) and there have been no complaints. I personally feel that all this concern over keyword breakage has no real evidence, its all theoretical. Java can just add a new keyword if they need to and no one complains. |
Beta Was this translation helpful? Give feedback.
-
Right. but the problem with that is that it direclty goes against design goals we have for these features. for example, we want you to just be able to say
I don't really see this as a burden. For people just using the language, using
This is not true. TAke 'go' for example. There are lots of complaints about the verbosity of the language. And part of htat verbosity arises because the language doesn't want to get into this space. So it ensures all it's constructs are extremely verbose and often unweildy, just so it doesn't have to do any semantic checks on this sort of thing. It's a tradeoff they made, but which we're quite loathe to as it really just bulks up the language. |
Beta Was this translation helpful? Give feedback.
-
I would need to review the proposal but isn't this going to work exactly like If there is a design goal that can only be achieve with name lookup rules or everyone else in the LDM just disagrees and thinks that semantic contextual keywords are awesome and we wish we did them more often great! Thats not my position but I am willing to be convinced. |
Beta Was this translation helpful? Give feedback.
-
No. 'value' always binds to the property parameter prior to anything else in a higher scope.
That would break lots of code taht is totally fine today and which wasn't doing anything strange or inappropriate. I do not see how customers are helped by just changing the meaning of their code on them.
We are not, and should be beholder to 'a casual reading of this'. If you see this:
What does a casual reading tell you? Almost nothing. This could be a local, or a field, or a property, or a parameter. it could be assigned. it could be assigned by-ref. it could have conversions. it could throw. etc. etc. etc. And that's just assignemnt. Once you get the |
Beta Was this translation helpful? Give feedback.
-
You say "Contextual keywords that are never syntactically ambiguous" but surely such situations would never compile, if the compiler and grammar can't resolve an apparent ambiguity then its a syntax error, no? Also is there any evidence behind the statement "the way contextual keywords were applied to a specific language (C#) make it more complex to use"? I've personally never found this aspect of C# even a slight problem, if there was a real risk that a syntactically valid program might execute in a very unexpected way because the author was misled by a contextual keyword then I'd certainly be interested to learn more of these cases. I suppose this is a candidate though for the kind of thing you're speaking of: public class record
{
} To a novice with C# - is that a record declaration or a class declaration?... |
Beta Was this translation helpful? Give feedback.
-
There are no syntactic ambiguities with any contextual keywords (except 'record', though that was done intentionally). |
Beta Was this translation helpful? Give feedback.
-
I covered this above. It would certainly be confusing, for example, if |
Beta Was this translation helpful? Give feedback.
-
Yes. This is one of the reasons we've approved making a warning for this. So we can tell users: this likely is a bad idea, and is likely very confusing. And this is just one case. If there were no keywords, then you get this with everything. |
Beta Was this translation helpful? Give feedback.
-
That's simply not true, if the grammar insists that every identifier must precede its attributes then there's no confusion whatsoever. The current grammar mixes the ordering of attributes and identifier and they way these are allowed to be mixed varies from one language construct to another.
If the name was always and had to always be, the first part of such definitions then a) there's no more confusion about what is its name and b) the ordering of the various attributes becomes irrelevant. With that said any developer can see that these are all logically identical: Mydata class public sealed
{
}
Mydata public sealed class
{
}
Mydata sealed public class
{
} Because the name must be the first token nobody can ever be confused about what is its name and the attribute ordering is utterly irrelevant in these examples. This also completely eliminates the current possibility for confusion with a I'm not suggesting this as a literal grammar either, just trying to show you how this could in principle be accomplished and to answer your post. |
Beta Was this translation helpful? Give feedback.
-
we keep going in circles @Korporal . This was already discussed heavily above. That sort of anachronism is too restrictive and would not be acceptable to any language we want to invest in. Indeed, we moved away from that in VB because it was simply too unpleasant and unwelcome by the ecosystem. Furthermore, you've continually asked if it would be possible to do this for the grammar of c#. For example: "I'm curious as to what a grammar would, could look like that strived to be as close as possible to the current C# syntax " It cannot be both close to the current C# syntax, and yet not support even basic constructs like this. At that point it would not only not be c#, but it would be such a departure as to not even feel slightly close to c#. Effectively, every syntactic construct would need a prefix form. And any place where an identifier could start would have to ensure that any following token both did not collide with any existing grammar construct today (already very not true), and for all future grammar productions we'd want in the future (very very limiting). As such, such an approach would not be viable or desirable. Furthermore, as stated above, there are practically no benefits to this approach. It does not solve any issues that we're having problems with. However, it introduces substantial issues both in the lang design space and the user-experience spae that make it a complete deal-breaker for C#, C#-prime, or any potential future lang. |
Beta Was this translation helpful? Give feedback.
-
This is not a virtue. This is a degradation in user experience. You are proposing a 'solution' to a part of language design that we not only consider non-problematic, but we consider a virtue. We don't have an issue introducing syntactic keywords. We have a solution for it. We also have a mechanism to allow users to use anything as an identifier if we've squatted on it. Allowing more keywords to be usable as identifiers in differnet positions is not on a non-goal, it's an anti-goal. It's something we do not want. As stated, it would be possible to have hte language do this. But we intentionally do not want it as it's a net negative for usability. |
Beta Was this translation helpful? Give feedback.
-
At this point, things seem to be going entirely in circles, and the tangent from teh core issue is enormous. Please open a discussion if you would like to discuss this further, or please take this to somethign like gitter.im/dotnet/csharplang. There's nothing really to be gained repeating the same points over and over here (esp. as they are on a topic that is unrelated to what this issue is tracking). |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
@Korporal, as specified above, please open a new discussion, or take thsi tangent to gitter and/or discord. Repeating the same points cyclicly isn't valuable (Esp. as this is a tangent on an idea that doesn't match this issue). This was my mistake for allowing this tangent to happen. I thought this was a github discussion, not a github issue. Free form exploration of ideas like this are what discussions are for. For direct issues like this, we want to keep things on topic to the issue itself and only what is relevant to that. |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
@Korporal, as specified above, please open a new discussion, or take this tangent to gitter and/or discord. As i said before i made a mistake here, believing this to be a discussion already and not an issue. That was my fault and I apologize for it. However, from this point on, any further conversation on this tangent is not appropriate for this issue. |
Beta Was this translation helpful? Give feedback.
-
lol! That is not the @CyrusNajmabadi way :)
@Korporal Sorry I was wrong here. I should not have said "syntactically ambiguous". As you say, it will parse to something. The question is whether that something is useful. The crux of this issue is that this is valid code in C# today: class await
{
async async async(async async) => await async[async][async][async][async];
} full code sampleusing System;
using System.Runtime.CompilerServices;
[AsyncMethodBuilder(typeof(builder))]
class async {
public async this[async async] { get => null; }
}
class await
{
async async async(async async) => await async[async][async][async][async];
}
static class util {
public static awaiter GetAwaiter(this await a) => throw null;
public static awaiter GetAwaiter(this async a) => throw null;
}
class awaiter : INotifyCompletion {
public bool IsCompleted => true;
public void GetResult() { }
public void OnCompleted(Action continuation) { }
}
class builder
{
public builder() { }
public static builder Create() => throw null;
public void SetResult() { }
public void SetException(Exception e) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine => throw null;
public async Task => throw null;
public void AwaitOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine => throw null;
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine => throw null;
p While this is a technical marvel from a parsing perspective, I ask the question "Does this make the language easier to use?" This proposal argues that is does not. If you read that sample above and say "That seems fine, or at least not harmful" then you certainly don't agree with this proposal. If you also want more language constructs to behave this way (which is what I am interpreting your statements as being about) I agree with @CyrusNajmabadi that we should have that discussion on a separate issue. I am happy to start that if you want. |
Beta Was this translation helpful? Give feedback.
-
I would say, let's keep |
Beta Was this translation helpful? Give feedback.
-
I agree there likely aren't many, but from what I understand, there are some big companies and/or government orgs whose code style policies are such that they never want to have But today there are much better ways to enforce such a policy: There's a whole section of EditorConfig rules for it, so there's a clear migration path for such code bases that wish to ban the use of certain keywords in their entirety while also (possibly?) making it easier for the LDT to add new useful keywords in the future. (That said, the EditorConfig section in question is only for |
Beta Was this translation helpful? Give feedback.
-
Only Allow Lexical Keywords in the Language
Summary
Today there are keywords in the language that cannot be understood with just lexical information such as
var
ornameof
. These keywords operate this way for backwards compatibility reasons. I propose that we change the language so that there exist no keywords that cannot be determined via lexical analysis.Motivation
In general, C# strives to be a language that is explicit about program behavior and normally requires the developer to write out what their intention is without ambiguities. This makes it a language that is easy for someone to read and understand. Once you learn it there is little implicit behavior to consider. I believe having this "gotcha" where keywords are only keywords if nothing else in scope is so-named makes the language harder to read and reason about in general.
There is also the reality that the design goals around C# Language versions and .NET Framework versions have changed. In the past it was paramount that developers could take a new language version update without updating the framework version they were targeting. With language features being increasingly tied to the runtime this makes less sense. We now strongly encourage developers to update both the language version and target framework together.
Detailed design
There is an existing concept in the language called "contextual keywords". I am not proposing doing away with this concept altogether just changing it so that a keyword's "contextual-ness" is always able to be determined lexically. Take new (at the time of this writing) keyword
record
. We can still know if we are referring to therecord
keyword or some identifier named record based on the lexical context, there is no ambiguity. Howevervar
, according to the spec, requires us to check if there are types named var in scope:spec
Similarly,
nameof
requires checking if a there are any identifiers called nameof in scopespec
The implementation of this proposal would remove wording from the spec around name lookup collisions, and have a compliant compiler be able to fully determine keywords given only parsing information.
The following keywords would now error if developers attempted to use them as anything other than a keyword
var
nameof
dynamic
_
Drawbacks
This is a breaking change, if anyone were relying on this behavior in their code it would no longer compile. For cases where a type is named
var
,dynamic
, or_
or a method is callednameof
the developer would need to change the usages to@var
,@nameof
,@dynamic
, or@_
.Alternatives
We could opt to keep
_
as a contextual keyword that depends on name lookup rules as this is the change most likely to break real-world programs (see discussion on #1064)Unresolved questions
Design meetings
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-28.md#ungrouped
https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-09-06.md#only-allow-lexical-keywords-in-the-language
Beta Was this translation helpful? Give feedback.
All reactions