-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Proposal: Destructuring (assignment?) statement #6400
Comments
Why let (int x, int y) = ComputePoint(); when you could have (int x, int y) = ComputePoint(); |
@mattwar I'm not sure what that syntax is supposed to be an example of. If you're proposing that we have a new statement form
Then we'd run into many syntactic ambiguities with the existing "assignment statement" and local-declaration forms. |
I'm not assuming anything about patterns. I'm assuming tuple deconstruction. As far as I can tell, a tuple deconstruction syntax without a let keyword is not ambiguous. |
I vote for: let x, y = ComputePoint() or let (x, y) = ComputePoint() |
@mattwar @tmat Sure, if we wanted single-level decomposition for tuples but not for any other data types or pattern forms, we could design a one-off construct for that use case. I believe that is not the only use case for decomposition. See, for example, records in #206. The proposal here would support struct Coordinates(double Longitude, double Latitude, double Height);
struct Destination(string Name, Coordinates Place); and then Destination d = ...
let Destination { Place is Coordinates { Longitude is var longitude } } = d;
... longitude ... // longitude is in scope here or, using positional notation Destination d = ...
let Destination(*, Coordinates(var longitude, *, *)) = d;
... longitude ... // longitude is in scope here and many other decomposition forms. |
What about
Implying a complete pattern. By the way, I didn't like these |
@alrz Are you suggesting that
Why? They have the same effect, except the former gives you a read-only variable. |
Yes, |
So I guess we would call this a "case statement"? |
@gafter That would be it. |
If I had to choose between ComputePoint() case (int x, int y); and let (int x, int y) = ComputePoint(); I'd choose the latter. I think it is a bit confusing to have a statement (other than an expression-statement) start with an expression. |
That is a
I admittedly, prefer expression first syntaxes, like |
@alrz The scoping would be entirely different, though. The pattern variables don't escape their |
I didn't say they are exactly the same but syntactically similar. I'd say it's a .Select(t => (let (int x, int y) = t; x + y));
.Select(t => (t case (int x, int y); x + y));
.Select(t => t match(case (int x, int y): x + y));
.Select(t => t case (int x, int y): x + y);
.Select(case (int x, int y) => x + y); That last line is from #6067 which I found most concise and expressive. The standard possible way would be using |
Which is why it doesn't work, the scope is all wrong. The rest of your reply seems to be irrelevant in the context of this proposal. This has nothing to do with lambdas or extending parameter syntax with patterns. |
.Select(t => (let (int x, int y) = t; x + y)); This would only make sense if we extend #6182 to include let statements, which we would if we do both #6400 and #6182. However it is not certain that we'll do both. .Select(t => (t case (int x, int y); x + y)); This is your proposed alternative, which I find less readable. .Select(t => t match(case (int x, int y): x + y)); This is already proposed as #5154. This issue is about a statement analogue that keeps the variables in scope. .Select(t => t case (int x, int y): x + y); This is an expression form not under consideration, nor does it have much to do with this issue (there are no statements in this example). .Select(case (int x, int y) => x + y); Ditto. |
They all contain a single case complete pattern, that's why I mentioned them, anyway. |
Implicit var in identifier-only version
should also extend to tuples (and records?):
|
Why not borrow ES6 syntax and allow the following
Or, maybe allow destructuring directly available in parameters
It feels that almost any syntax is terse and unreadable. |
What would this look like if |
And where was I change meaning of legal code?
What I would like to propose is to add it functionality
And as I said if you really care that const must never be accept any runtime changed, I could accept And I don't see the benefit to not permit const to use as readonly Man, as I said. If we talk about semantic, you should not allow using |
@HaloFour If you really think it up to C# team to decide then you would stop argueing with me now This is political debate that you and I have our own agenda. I don't like But don't try to mislead me. They would decide with our voice and reason has some weight so we debate here. You should not make political lying to stop other people |
So, having a completely new context for And, again, |
@Thaina Constants will be erased at compile-time but |
@HaloFour Because I think it not so difference. As I said, from C and C++ we were using const keyword at parameter to make it immutable. That is also a purpose of const
In the world right now how many const you would used to make it in compile time. How many you want it to be immutable? What people used cases? Actually this decision should be automatically decide by compiler as a compiler optimization. If it could be compile time constant then compiler would just compile it as is. If it is able to changed at runtime then just compile it as immutable, done And your argument about "expect
|
and if it does, who's responsible? I'm not going to jail for this. |
@Thaina I think the use of |
Because the two meanings are used in two completely separate and distinct contexts.
If you say so, but semantics are important. Existing code and libraries depends on C# doing what the spec says. If the semantics were to change then the resultant IL could change unexpectedly which can result in breaks. And there's no reason to have
Contextually different, not semantically different. Big difference between the two. I'd be perfectly fine with
Now there's a good point. You've made your case, everyone else has made theirs, why not just let it be? |
|
;-) |
Using Which I go against the first and accept the latter while you think opposite. But we have our own reason of "breaking change" As I said I could accept contextual difference from outside scope but I hate the lesser scope go outside. Because it would be use somewhere outside already. And if you really hate semantic change I would like you to consider But then again you never look at it |
@HaloFour And I said this
To only YOU. Because you are the one who think it up to C# team to decide not ME What I think is I should state my proposal and try to make argument to have some chance that my idea would affect their decision You are the one who make that invalid statement even you yourself don't belief in. Because if you really belief that it up to C# team to decide then you would stop arguing. While I continue because I don't belief the same thing as YOU If you really belief your word. Make example by your action |
This has been folded into the pattern matching spec. |
The spec has been moved
The spec for the proposed
let
statement has been moved to https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.mdBelow is a snapshot that may be out of date.
Inspired by an F# feature and a conversation on github, we could support decomposition like this:
let
is an existing contextual keyword.The form
is shorthand for
(i.e. a var-pattern) and is a convenient way for declaring a read-only local variable.
Semantically, it is an error unless precisely one of the following is true
else
clause is present.If an
else
clause is present, it is an error if the endpoint of its embedded-statement is reachable.Any pattern variables in the pattern are in scope throughout the enclosing block. They are not definitely assigned before the
else
clause, and are definitely assigned after the let-statement. It is an error to use these variables before their point of definition.A let-statement is a block-statement and not an embedded-statement because its primary purpose is to introduce names into the enclosing scope. It therefore does not introduce a dangling-else ambiguity.
The text was updated successfully, but these errors were encountered: