-
Notifications
You must be signed in to change notification settings - Fork 4.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
WITHDRAWN #14697
Comments
Binding to existing variables probably needs a different syntax (#13400). Note that this is what we need to do with out parameters. you need to declare variables beforehand. So it doesn't add much value to out var. |
I don't think that the implicit variable declarations is a good thing. In particular, it helps to hide typos. Consider:
Now, the value of |
They cannot be properties, because there is no way how setting a |
I like eliminating the implicit leaks by using the old style way of using local variable declarations to control scope. I don't like 1. the typo prone unification magic of this proposal 2. specifying the type of a variable more than once. A better proposal would be more akin to something like: int a;
foo(out a);
// or maybe a different keyword than "out"
if (3 is out a) { stuff; } |
@Kaelum Well, detecting typos is a primary reason why we need to declare variables at all. If we would consider guarding against typos not important, we could omit |
The variable being introduce should be to outer scope be default if( !(o is int i) )
{
/* i is in scope and definitely not assigned */
throw new ArgumentException("Not an int", nameof(o));
}
/* i is in scope and definitely assigned. */ and explicitly require a code to specify a change to the inner. For example by prefixing if (o is int ~i)
{
/* i is scope and definitely assigned */
}
/* i is not in scope. /* if( !(o is int ~i) )
{
/* i is scope finitely not assigned */
}
else
{
/* I is scope and definitely assigned */
}
/* i is not in scope. /* i prior exists int i;
...
if( !(o is int i) )
{
/* i is in scope and definitely maybe assigned */
throw new ArgumentException("Not an int", nameof(o));
}
/* i is in scope and definitely assigned. */ int i;
...
if (o is int ~i)
{
/* i is scope and definitely assigned */
/* also is and error as i is be reused for a variable declaration */
}
/* i is in scope. /* int i;
...
if (o isnot int ~i)
{
/* i is scope not assigned a new value*/
/* also is an error as i is being reused for a variable declaration */
}
else
{
/* i is scope and definitely assigned a value.*/
/* also is an error as i is being reused for a variable declaration */
}
/* i is in scope. /* if the type of |
Actually, that spam made me think of something that possibly could solve this issue. I'm totally against allowing scope escaping by default, but if someone really wanted it (for whatever reason), what if they could opt-in to that behavior? I'm specifically thinking about an otherwise illegal token, where maybe Example:
If something like that could work, it would allow sane scoping rules for the vast majority of cases, while still allowing them who wanted to take aim at a foot and pull the trigger to do so. |
I've looked into this bit, and i'm thinking it's not a good approach going forward:
From talking to >10 devs, (backgrounds in C/C++/Java/C#) every single dev found it unwelcome and surprising that such a declaration would implicitly use a declaration already in scope. They either expected a new variable that hid the existing variable, or a compiler error for the clash (even when the types matched). Cheers! |
There is a suitable large number of requests that people be able to use the new "out var" feature to replace code that used to explicitly declare the variable before use. As such, the above point no longer holds. People do want the ability to use 'out var' with similar scoping to how they used to have to use 'out' before. Talking to these people, they find it cleaner to do things this way, and find the scoping intuitive as it simply matches the scoping that they were used to. In other words, 'out var', to them, is just a simpler way to write the feature they have today. Having 'out var' have limited scope lessens the feature for them as it makes it too restrictive for the code cases they have today with 'out'. And, if the new feature doesn't fit nicely into the code they have today, and doesn't cleanly let them move that code forward, then they don't view the feature as an improvement for them. As such, i think it's worthwhile that the feature be useful to the largest set of users possible. Wide-scoping provides that. It enables the feature for people who want to move existing code forward, while not restricting hte feature from those who would prefer narrow scoping. The only onus on the narrow-scoping usage is that fresh names be picked. In other words we had these options:
In the interest of making the feature widely applicable and useful to all users (not just those who prefer narrow scoping), we went with '1'. Thanks! |
Your solution is not pleasant to those who want wide scoping. There are people who want wide scoping without the need for extra statements. We think the solution provided so far can provide that without being unduely unpalatable for those who still prefer narrow scoping. |
Please continue questioning anything you don't like and providing feedback as to your POV. It's really appreciated and helps a lot when we get together to design and make decisions on these sorts of things. By getting feedback and information from a wide variety of sources we can truly work toward solutions that we think will be hte best for the community overall. Note that even if we think something is best overall, that doesn't mean we think that everyone will like it :-) We're fully cognizant that there have been nearly zero changes we've made to the language that have been received positively by the entire community. Nearly every change is unpalatable to some (including me sometimes :D ).
Ultimately, we will make a decision here, and some developers will be unhappy. Were we to take the narrow scoping approach, then there would definitely be some upset developers. :) At some point we end up taking in all the feedback and deciding on what to do (which occasionally includes not doing anything). But, if we feel like we understand the space well enough, have received more than enough feedback to make a decision, and feel the overall feature will be a sufficient net positive, then we move forward on it. For those who do not like the decision, i can see why you might describe it as something being "force[d] down our throats". However, please recognize that with pretty much any decision, some group is going to feel that way. Unless 100% consensus can be reached on new feature (which we've literally never been able to get given that there are groups that are adamantly against any new features at all), some group will always have the language go in a direction they do not want. While i'm sympathetic to being on the receiving end here (after all, i've routinely been there myself), it's not something that should prevent change if we think the overall benefit is worth it. Thanks! And please keep the great feedback and ideas flowing :) |
Could you clarify this bit. What scenario 'completely breaks'? Thanks! |
Yes. that is understood. If you want a narrow scope, you can't have that. But you can at least still use the feature and not take advantage of the wider scope if that's not of any interest to you. The converse is not true. If we made the scope narrow, then there would be no option for those that want a wider scope. They would be locked out of the feature. I'd rather have both camps able to use the feature, even if suboptimal for one camp. Cheers! :) |
How is scope broken? Every existing C# 6 scope works exactly the same way as it used to. We're only adding a new feature and defining precisely what we want the scope of that to be. It's unclear to me how anything is 'broken' here :)
Given how many people we've talked to who don't think anything is breaking here... it's not clear at all that there's any sort of consensus that what you're talking about it happening :) -- Heck, we've made scope choices in C# in the past that were unfortunate (like how foreach scopes worked). We even were willing to change them (including accepting the breaking change fallout). At the end of the day, the sky was not falling. No 'partners' (enterprise or other) were really 'put out' by these decisions :) We're simply talking about a facet of a language feature. But it seems to have taken on life as something of life or death consequences :D |
It's not clear to me how 'narrow scoping' is 'required'. :) I think that's the disconnect. |
I bet Microsoft assumed that they were making the "right decision" when they violated these simple tenets previously with C, only to have to follow up with breaking changes and yet another dialect. I still know organizations that cannot migrate off of Visual C++ 6.0 because of those bad decisions. The syntax and grammar that C# chose to adopt comes with an assumption of behavior, including scope. Sure, C# has deviated in a variety of areas, particularly where it beat C++ to the punch (if Apart from the insanely late timeframe of these changes (seriously, you're talking RC2 here, there should be nothing even remotely up for discussion), what's worse is that this decision pollutes the entire future of pattern matching in the language. All because a few lazy developers don't feel like predeclaring their variables? |
Please be respectful. No one is disparaging you for the style of code you like. :) We have many developers who use are product and who evaluate things on a wide variety of axes. One particular developer (or group)'s usage of the language is likely to not at all be representative of the whole. Our goal is to evaluate our features against the broad spectrum of our users and come up with balanced approaches that we think will maximize the overall benefit to the larger ecosystem. |
We do not agree. We set our on schedules and we feel there is more than enough runway to both continue working and implementing language features. I'm sorry you feel otherwise. However, the control of the C# schedule is in the hands of the LDM and the compiler team. Both of these groups feel like there is enough time for the work we are doing. Both for getting implementation quality high enough, and for vetting if the language choice meets the goals we're setting out. |
I don't know what "simple tenets" you're referring to :). The LDM has a ton of experienced minds who are deeply familiar with dozens of languages. This choice doesn't seem to be particularly contentious or out of line with anything we've seen elsewhere. |
What are you referring to specifically here? Thanks! |
They do all the time, and that's fine. Where that stops being fine (for me) is where it becomes legislated as part of the language. I call into question the motive behind these decisions.
It's completely in opposition to the standardized behavior of C++. I would hope that the LDM has at least a passing knowledge of that language. |
@CyrusNajmabadi I will admit that I have watched a large number of the language design meetings and have been disappointed that you aren't recording them anymore. Any chance you'd do that again? |
They didn't see it that way. Look, at this point i'm not sure what you want :) You seem emphatically unhappy that different people view the language (and different facets of it) in a different manner than you do. I can't help with that :-/ I've literally just discussed this with a coworker, and he views definite-assignment as completely unrelated to scoping. So whether or not something is guaranteed-readable or not makes no difference to him in terms of what scope it should go into. This is someone who's been using C# even when it was called COOL. :D A really crucial thing to recognize is that developers are hugely different and they use and perceive the language in vastly different ways. I know that first hand when i've talked with people and they've talked about features that i know intimately in terms that feel totally alien to me! It's not my job to insist that people come to my worldview. It's my job to best try to understands so many of the worldviews out there and to try to come up with solutions that feel like they'll be sufficiently beneficial to them. To be clear: that even means designing features that i personally think contain parts that are 'broken' wrt to how i'd like to see them implemented. I have never shipped a version of C# that has not been that way. But, ultimately, i'm not making the language for me. I'm making it for me and tons of other devs out there :) |
Possibly. I would accept it if the team felt it was appropriate. Though i personally hate being recorded, and i find it quite stifling. :-/ |
@Kaelum Why did you change the title? and okay you actually deleted the post... that's odd. 😄 Managed C++ was ditched you probably mean C++/CLI. 😉 |
I agree that they are different concerns. However, it makes little sense for the language to introduce a variable into a scope where the compiler can guarantee that the variable is definitely not assigned. It would be a different matter if the compiler simply couldn't make the guarantee that it was assigned. As for the visibility/transparency, I continue to state that this particular case is the anomaly and that the language team has generally done a much better job. And while you are continuing to explain the concerns tidbits continue to come to light after the fact. A big example was the reversal of immutability of variable patterns, which only came to light in a comment after it was pointed out that variable patterns are near useless in a wider scope when immutable. Big decisions like that should be front and center. As for the "scientific-ness" of any particular survey mechanism, I was calling into question SurveyMonkey. But I do think that its a shame that this dialog that you guys conducted with "hundreds" of developers was not extended here. |
@HaloFour I hear you. I think we'll def be taking cases like this into account when we do stuff in the future to try avoid unhappy kerfluffles :-(. Note that this is a generally hard problem for us as well. We get feedback from some that "you did things on github, but i had no idea since i don't use that" :-/ It's going to be an interesting problem figuring out a changing communication model with so many parties. |
@CyrusNajmabadi WHO ISN'T USING GITHUB?! hunt 'em down! we can't have dat! 😆 |
Hey! I'm still trying to figure out if i should use teams, slack, yammer, gitter, skype, or outlook... sigh.... |
@CyrusNajmabadi Use IRC! and build bridges! |
For posterity, here is the conversation right before OP ragequit: |
@jnm2 Cool mate! thanks. For future reference I've copied the source from the link: The C# Design Language Notes for Jul 15, 2016 in #12939 are deeply concerning, and should be raising a red flag for everyone. Allowing a C based language to leak like this, throws out the more than 45 years of scoping rules that exist. It also allows variable declarations to be hidden, making them extremely difficult to find. I am saying this now, as people are just starting to realize the gravity of #12939. As an additional side effect #14651 was created, and there will very definitely be many more to come if this is allowed to remain as-is. All of this, just to allow a "nice to have feature"? My proposal is to revert the scoping rules back to the way that they were prior to #12939, and change the implementation of the If anyone needs the "leaking" functionality of #12939, no changes need to be made. We have that ability in C#6 and earlier, where you just explicitly declare the variable in the scope that you need it. However, for those who would like to use "temporary" variables, which was the original vision of this, you will have many options. Consider the following: For those who don't want the leaks:
For those who like it leaky:
In no case would I want
If I truly want
Remember, it is our duty as developers to question anything, and everything, that someone is trying to force down our throats. It took well over 10 years to create the 1998 C++ specification, and I thank everyone who was involved for ensuring that absurd proposals like #12939 never saw the light of day. Have an AWESOME day! |
Could we have the same analysis for this pattern?
With current scoping it could be rewritten as: if(!(typeSyntax is SimpleNameSyntax simpleNameSyntax)
{
return typeSyntax;
}
// simpleNameSyntax in scope However, IMO #6400 or #14239 are better solutions compared to a negated let SimpleNameSyntax simpleNameSyntax = typeSyntax else return typeSyntax;
var simpleNameSyntax = typeSyntax as SimpleNameSyntax ?? return typeSyntax; (my point is that with the above constructs there is no nead for is var to leak.) |
@alrz The presumption in all those cases is that the 'other/else' branch you are performing is always simple. That's not been the case in a lot of the code i'm analyzed. It's common enough for there to be more more logic going on there that takes at least multiple statements to perform. |
I'm thinking that the point is to avoid nested ifs/additional indention level. So currently the best way you'd come up with is the inverted if which requires the scope to leak (in case you've used pattern matching to do the same). however, The other/else part you are referring to is simply the rest of the code, yes? That's the case in the code that I linked to and my alternates would just work. Not sure what I'm missing here. |
@CyrusNajmabadi Would it make sense if you (or someone else who has the rights) restored the topic title and possibly also the first post and reopened the issue (assuming you don't consider the discussion to be over)? At the very least, the topic title should reflect the topic, so that people can find it. |
@svick Great question. I'm not sure about the ethics of changing someone else's thread... Maybe if i did it and made it clear what had happened? Let me discuss this with team members. If you did want me to reinstate the original post/title, please let me know (+1's will suffice). Thanks! |
@CyrusNajmabadi This someone deleted his account so you don't have to worry about it. 😆 |
I'm wary about going an editing anyone else's post. At least not without making it 100% clear what happened. I'm not sure if that's considered a big no-no, or would otherwise be veyr much frowned upon. I'm totally willing to do it if i can get enough confidence that the team/community feels like that's ok. |
@CyrusNajmabadi Well, to be honest, if the guy deleted the post, then went on and deleted his account after people here discussed it and he did it with no reason or real explanation then I'd say it's okay because that's rude! p.s. I think you need to label this as discussion too. |
@eyalsk I don't disagree :) And i'm not opposed to doing this. I'm just going to chat with my team to make sure it's totally 100% above board first, ok. I want to make sure we have an atmosphere of trust and responsibility here. And that means being careful around things that people could be very sensitive to. Note: i have no problem reopening this. So i'm going to do that now. :) Thanks! |
Also, for those unaware, we're discussing a concrete proposal on a small tweak to scoping over here: #15529 My preliminary analysis tells me we should do this and it would certainly wall off one area of scoping-concerns that people have raised. |
Us? Sensitive? Nonsense, I say... (realises there's no "gets coat" icon, so that's a meme possibly lost on non Brits 😉) |
We've tweaked scoping for variables declared in while-loop conditions. I've given an explanation of what we intend to do here: #15529 (comment) Note: our discussions are not over, and we are still examining and evaluating the features for C# 7 to see if there are other things we can do :) |
Issue withdrawn by OP. |
We've decided to switch to C++/CLI.
The text was updated successfully, but these errors were encountered: