-
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
Proposal: list pattern #3435
Comments
Awesome. Is this going to build on the linked proposal (with your additional feedback) or is this to track the work of designing list/collection/dictionary/etc patterns in general? |
@HaloFour This is to track answering questions like those. |
I wonder how you'd imagine dictionary/indexer patterns work and what use cases you have in mind. Syntax-wise it could be |
Maybe we could use a |
To me, that's too specific to have a dedicated syntax for. I think we should enable patterns for all Try-like methods which is essentially what user-defined positional patterns are. map is TryGetValue("constant key", pattern) // maybe with another name This could made to work only on "some" methods as mentioned in #1047 (comment) Syntactical symmetry with indexer initializers makes it attractive though, however, the fact that it would not call the indexer might be confusing. |
Would this allow something like Array: { Length: 1, [1] } checking whether there is only one element and whether that element is |
The pattern To match Nth element you could prepend N-1 discards - it tends to get long but it is definitely possible. The team is interested in supporting indexers, so using range indexer pattern, we could support I'm not sure if that's common enough for a dedicated support, plus it won't work with generic dictionaries which is probably a deal breaker. |
I'd generally much prefer |
Does this proposal also include list decomposition? List<int> my_list = .....;
{ int first, int second, .., int last } = my_list; |
No. That's #4082. |
@jcouv We've been hearing quite a bit about this from several community channels (twitter, discord, etc.) Can we bring this to an upcoming meeting to discuss and make some decisions on? Thanks! |
@CyrusNajmabadi Will do. |
reading the design meeting notes, if the eventual outcome is that we can also replace:
with
I'll be very pleased. It's one of the things that jars when I work with 3 different languages in my day job (C#, Typescript/json and Python) |
That's a normal subpattern, it's not special for list patterns. C# always requires |
Quite verbose. |
Your code already has meaning :) |
Very often opposite of verbose is not concise, but cryptic. Nobody wants things to be more verbose than needed, but trying to go further than that just results in obfuscated Code that's needlessly difficult to read and maintain. |
The |
Being list-patterns a typical functional paradigm I'm just proposing what is common in functional languages. I fail to see in what manner, in this precise context, making var optional obfuscates code. |
@emperador-ming As i mentioned above, that code already has meaning. It means "match if the list contains this value as the first element in it". Thanks! :) |
What is good for other languages isn't necessarily good for C#. As mentioned, this has nothing to do with list patterns. That is just a normal subpattern, and variable subpatterns always require the typename or |
Correct me if I'm wrong, but in this context these variables don't vary at all. They're just expressions. |
Variable patterns introduce normal variables. They can vary in that variables in C# are mutable. |
If if (buttons is [{ Tag: SomeConstant }]) |
Even if it's optional? |
if (buttons is [{ Tag: var someVar}]) This means: Store the |
Can we combine collection expression and u8 literal? var dat = new byte[]
{
130, // Map 2
161, 65, // "A"
171, 83, 111, 109, 101, 32, 83, 116, 114, 105, 110, 103, // "Some String"
161, 66, // "B"
174, 65, 110, 111, 116, 104, 101, 114, 32, 83, 116, 114, 105, 110, 103, // "Another String"
};
// <PackageReference Include="MessagePack" Version="2.3.85" /> in the csproj
var json = MessagePack.MessagePackSerializer.ConvertToJson(dat);
Console.WriteLine(json); // {"A":"Some String","B":"Another String"} And I'd like to rewrite this as follows: var dat = new byte[]
{
130, // Map 2
161, .."A"u8,
171, .."Some String"u8,
161, .."B"u8,
174, .."Another String"u8,
}; |
i think that would work... |
Here's why, as per the rules we came up with.
|
Is that really related to list pattern? I think it is all about splat operator. |
It is not, and that's why I suggested having the conversation at #5354. |
Yes, but I already have the right answer: #3435 (comment) |
So what's the current stance of lang team about changing Looks like C# 11 is getting finalized and we stayed with |
@mpawelski there is no change to the design coming. |
That was discussed in LDM here: https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-03-09.md#ambiguity-of--in-collection-expressions. |
https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/list-patterns.md#lowering specifies that
When trying out the same code on SharpLab it generates the code below which includes a null check on public bool M(int[] expr)
{
if (expr != null && expr.Length == 3 && expr[0] == 1 && expr[1] == 2)
{
return expr[2] == 3;
}
return false;
} Is the compiler over-implementing list patterns by always including a null check, or is the language construct under-specified and should say that the compiler must emit a null check if it cannot prove It might be that I'm simply misunderstanding what "equivalent" means here, i.e. how much the compiler can diverge from the specification. |
The spec is incorrect. It should say there is a null check. |
Allow
is [ 1, 2, 3 ]
(list pattern),andis [length]
(length pattern)is [ 1, ..var x, 5 ]
(slice pattern).Speclet: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/list-patterns.md
See #3245
LDM Discussions:
The text was updated successfully, but these errors were encountered: