-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Champion "deprecate _ (underbar) as an identifier" #1064
Comments
Edit: I've changed my position on this: #4460 (comment)I use |
Relevant previous discussions/arguments/rants: dotnet/roslyn#14794 There might be a few more. I think it's worth the discussion although it would probably be difficult to resolve without breaking a lot of existing code, particular like @jnm's example. 🍝 Perhaps the rules for identifiers could allow underbar for a lambda parameter in expression lambdas but not elsewhere? That would be weird. At the very least perhaps consider adding a warning wave to declaring a field or local using the underbar identifier. You could differentiate the discard/local case by whether or not the local is ever used. |
If there was an auto-upgrade conversion of existing usages of |
The point of |
@jnm2 Agreed, it would just keep from breaking existing code. |
I'd stop using |
@jnm2 Indeed, it would be awesome if they would at one hand get rid of |
I'd support any kind of deprecation at this point. This seemed impossible to me but now I can see the light. Please deprecate more. |
Is this seriously being considered or is this just a wish? Has the LDC suddenly had a change of heart where they're willing to take breaking changes? |
What does "deprecate" mean in this context? I assume it wouldn't be a full removal from the language? |
@yaakov-h I assume that in any place where today you can use a single |
I recall that something like this was already planned to be the case. And the whole process would likely be spread out over a few major language versions, regardless. (So for example, 8.0: Info, 9.0: Warning (maybe with exclusion from |
Stumbled on this by accident and just had to add my 2c. I'd be very happy if As someone who makes heavy use of Rx, being able to discard with this.WhenAnyValue(
x => x.DepartureLocation,
x => x.ArrivalLocation,
x => x.JourneyMode,
x => x.JourneyTime,
x => x.ShowAll,
(_, __, ___, ____, _____) => Unit.Default) Having said that, I understand concern from @jnm2 et al regarding breaking changes. Personally, I think items.Select(item => ...) But of course, now we're getting into style arguments... |
There's no reason we couldn't have this, and there's even a proposal on it: this.WhenAnyValue(
_ => _.DepartureLocation,
_ => _.ArrivalLocation,
_ => _.JourneyMode,
_ => _.JourneyTime,
_ => _.ShowAll,
(_, _, _, _, _) => Unit.Default)
|
Er, yes. It's what I'm asking for. But it would require that this proposal be accepted so that
It was a very simple example based on yours. Add a |
The code sample uses
Though in fact it's most predominantly used only once in a chain, I do this on a regular basis and like it: foos.SelectMany(_ => _.Bars).Any(_ => _.Start != null || _.End != null) The project I have open: 16.9% of the files use |
Ah, I overlooked your use of |
@eyalsk I'd assumed a compiler warning for a while, up until it is outright disallowed on the next major language update (or whenever). |
Attention please Why not make it an option to enable/disable usage of discards all over the place? like how unsafe is optional. that way it wont be breaking change. |
Whilst this is a breaking change, it is only breaking if one uses "treat warnings as errors" (which hopefully we all do; oh to have that as the default in new projects!) and it need only be breaking for as long as it takes to select a "ignore this warning in this project" code fix. |
@DarthVella Yeah, probably. :) |
Warning in v8, error in v9 seems a nice timeline for phasing out the use of |
@DavidArno Yeah this is what I wrote in a comment to @MkazemAkhgary in his post. ;) |
for a very rare case,
|
I'd personally like to see all underscore-only identifiers deprecated, even though I know this would break some of my own code (and thus the code of anyone who uses my library). The benefits of clarity would outweigh the small pain of fixing that broken code in my view. |
@gafter My previous understanding was it's possible to automatically turn all 📝 With this behavior in place, an analyzer could be used to deprecate 📝 I have some code bases which this change would break. It wasn't commonly used, but I'm loathe to change the affected cases because they are in some of the more stable parts of code I've worked on in the past (approaching zero churn). |
@gafter thank you for the clarification.
You're making me feel philosophical ♥ @DavidArno I disagree about deprecating |
Visually, _ is good because it 'aerates' the display and I use _ extensively as (_ =. _.Data). If it gets deprecated, then I would also agree that (@.Data) would work; But don't deprecate something until there is a better replacement. |
There is an old saying in .NET API world: once something is released you are stuck with it for lifetime. Reason: do not break existing code. The same applies to C# language requiring guarantee for backward compatibility. IMO weather someone likes it or not "_" - underbar is available as an identifier and it should remain to be available in the future. Perhaps it would be better to extend design and prototyping stage for C# features to avoid that kind of issues in future rather than messing with existing code. |
Absolutely what they normally do, but this was a bikeshedding issue. |
@4creators and what would you do currently in this situation when all other characters are in use? Probably we could use some Emoji instead? It's good when language is backward-compatible, but sometimes it limits you without giving worthwhile profit. You can't develop language in centuries and still backward compatible. So I'd like C# to evolve and loose some of these features like underscore identifier rather than see it slowly dying because of focusing on backward compatibility too much. Especially when we have wonderful public static IEnumerable<T> Pipe<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (action == null) throw new ArgumentNullException(nameof(action));
return _(); IEnumerable<T> _()
{
foreach (var element in source)
{
action(element);
yield return element;
}
}
} I spend, don't know, half of minute until I realized what's happening here. It's weird, it's confusing and spending so much time for that simple code is not ok. So I would happy if this doesn't compile. |
Evolving language does not have to loose backward compatibility. Just look at how C++ has evolved over last 10 years and it allows for a lot of bad, and hard to understand code and at the same time you may find quite a lot of beautifully written code. It is the users of language who make it easy or hard to understand usually the same goes true for natural languages as well. |
that's unfair argument, you can always write hard to understand code, you can always abuse options you have in hand. |
You know, this example doesn't help you as well as it helps me. C++ become almost unsupportable because of this and sometimes it's better and easier to understand code on another language, e.g. Rust, than other C++ guy's code.
I understood this example as a sample of underscore-identifier feature fair use, not abuse. |
You are right; a language doesn't have to sacrifice backward compatibility to evolve. But your example of C++ proves why always keeping backward compatibility leads to problems. Sacrifice backward compatibility in a few cases and the language can evolve cleanly, not end up like a dog's dinner like C++. Breaking backward compatibility just for the sake of it is not good. But occasionally, breaking it really helps. Getting rid of underscore-only identifiers would really help. |
I think
|
@MkazemAkhgary you don't choose between |
@Pzixel if I don't see how |
@MkazemAkhgary Well, if they will deprecate it then it will probably take some time before it's going to be completely disallowed whereas |
@MkazemAkhgary if Hey, Java 9 has also deprecated underscore. It seems that this restriction actually has a real value. |
there are 3 ways I can think of, but I think only one of them should be eligible.
In my opinion, option 3 is best. don't rush on things, wait for language to slowly become evolved but in much cleaner form and shape. |
Thanks for the three point description, as I was getting really confused by the talk of However, I have to say that I think option 3 is a truly awful idea. Removing |
On the other hand, it looks like F# might get |
Once again bringing up Scala's design, that's exactly what they have and it's fine most of the time, though it does cause some confusion for newcomers in certain scenarios with lambdas. Overall, I still think option 3 is the best one to have. We're a little bit in subjective syntax ground here, but for me |
Kotlin uses val user = users.filter(It.name == "Foo").singleOrNull(); |
Just ran across this: fixed (char* _ = str)
{
// ...
} The pointer is not used, so it's a more efficient equivalent to this: var pinningHandle = GCHandle.Alloc(str, GCHandleType.Pinned);
try
{
// ...
}
finally
{
pinningHandle.Free();
} |
I have a jQuery-like code library. instead of I believe that running analysis on github repositories for detection of use cases for |
This is not the case. The proposed change isn't "just because we do not like it". It is because Thus the proposal: remove |
This should have been thought about when the discard |
Pattern-matching will not permit you to reference a constant named |
It is unfortunate that the reader cannot easily distinguish at the use site between a discard and a use of an identifier named
_
. Presumably the latter is rare. Programs would be easier to read if one could reliably depend on_
being a discard.The text was updated successfully, but these errors were encountered: