88 lines
6.4 KiB
Markdown
88 lines
6.4 KiB
Markdown
# C# Language Design Meeting for December 14th, 2020
|
|
|
|
## Agenda
|
|
|
|
1. [List patterns](#list-patterns)
|
|
2. [Definite assignment changes](#definite-assignment-changes)
|
|
|
|
## Quote of the Day
|
|
|
|
- "They are syntax forms you little devil. No amount pedanticism is too much in C#."
|
|
|
|
## Discussion
|
|
|
|
### List patterns
|
|
|
|
https://github.com/dotnet/csharplang/pull/3245
|
|
|
|
Coming out of [Monday's meeting](LDM-2020-12-14.md), we had a few different competing proposals for syntax. As a quick recap:
|
|
|
|
1. The original proposal as is.
|
|
2. Put the brackets from 1 inside the braces on the top level.
|
|
3. Use braces for the list pattern, with the empty case being:
|
|
1. No empty case.
|
|
2. `{,}`
|
|
3. Add a `[pattern]` form that allows testing and potentially extracting the length of a collection.
|
|
4. Add a new combinator to make the braces explicitly a list pattern, which would allow `{ }` to be the base case.
|
|
|
|
After the notes were published, we took the list and had an email discussion to narrow in on the specifics of each of these cases.
|
|
Cases 2, 3.i, 3.ii, and 3.iv were not defended in this email chain, and coming into today's meeting there were 4 different main syntax
|
|
proposals, the final 3 being variations of 3.iii from the original list (in psuedo-antlr):
|
|
|
|
1. The original proposal. This introduces a new `pattern`, which uses `'[' (pattern (',' pattern)* ']')` as the syntax of that
|
|
new pattern. This cannot be expressed as a top-level concept in a `positional_pattern` or a `property_pattern` because the braces
|
|
can be ambiguous with the `type` component of these patterns.
|
|
2. `type? ('(' subpatterns? ')')? ('[' pattern ']')? ('{' property_subpatterns_or_list_element_patterns '}')?`.
|
|
This form modifies the `positional_pattern` syntax introduced in C# 8 to add a length pattern section, defined by the middle
|
|
`[pattern]` section, and modifies the final braces to contain either a set of positional subpatterns, or a set of list element
|
|
patterns, but not both. To test both property elements and list elements, a conjunctive pattern needs to be used.
|
|
3. `type? ('(' subpatterns? ')')? ('[' pattern ']')? ('{' property_subpatterns '}')? ('{' list_subpatterns '}')?`.
|
|
This is very similar to 2, except that it allows both property and list subpatterns at the same time.
|
|
4. `type? ('(' subpatterns? ')')? ('[' pattern ']')? ('{' property_subpatterns_and_list_element_patterns '}')?`.
|
|
This is very similar to 2, except that it allows both property subpatterns and list subpatterns in the same set of braces. Consider
|
|
subproposals of this version to require properties first, list elements first, or no ordering requirements.
|
|
|
|
The very important goal for the language team here is to follow the correspondence principle. That means that if you construct using one
|
|
syntax construct, you should use the same construct to deconstruct. For collection types, this means that we strongly want to prefer
|
|
using curly braces as the deconstruction syntax, rather than square brackets, because collection initializers use the braces. It is
|
|
possible that at some point in the future, we could add a collection literal syntax that uses square brackets, but there is strong
|
|
history in C# to avoid using the brackets in this fashion. Up to this point, the brackets have always contained indexes or lengths
|
|
in the language, and lists of things to initialize have always been inside braces. Changing that at this point, even if we later seek
|
|
to add conformance by introducing a new collection literal, would be asking C# users to unlearn a concept that has been unchanged
|
|
since C# 1.0, which is very concerning to us. Given this desire, option 1 deviates too much from existing C#, and we will instead
|
|
focus on one of the latter options.
|
|
|
|
Of these latter options, option 2 can be viewed as a strict subset of both 3 and 4, as either will allow using conjunctive patterns
|
|
to separate out the list and property patterns if users feel that the combination is unreadable. Additionally, we again turn to the
|
|
correspondence principle: today, you cannot combine both collection initializers and object initializers. By the correspondence
|
|
principle, then, you should not be able to combine them in the same pattern during deconstruction. We're not necessarily opposed to
|
|
allowing collection and object initializers to be combined in the future, but that is out of scope for the collection pattern changes.
|
|
|
|
Finally, in discussions Monday and over email, we also took a brief look at indexer patterns as possible `property_subpatterns`. These
|
|
would look something like this: `{ [1]: pattern, [2..^4]: var slice }`. This form seems like a good next step after list patterns to
|
|
allow deconstructioning objects with indexers. These indexer arguments could allow non-integer constants as well as multiple arguments,
|
|
giving a deconstruction mechanism for dictionaries that corresponds to object initializers in this area.
|
|
|
|
#### Conclusion
|
|
|
|
We'll move forward with the general syntax proposed in option 2, with a length subpattern and allowing either property subpatterns or
|
|
list subpatterns in the same "recursive pattern" section. We still need to translate the psuedo-spec above into a formal specification.
|
|
We also did not address the open questions around whether the length pattern should be applicable to types of `IEnumerable`, and if so
|
|
whether `[0]` is the only allowed pattern or if any pattern is allowable.
|
|
|
|
### Definite assignment changes
|
|
|
|
https://github.com/dotnet/csharplang/discussions/4240
|
|
|
|
This is an area of longstanding pain for C# users: any time conditional evaluation and comparison to constants mix, definite assignment
|
|
cannot figure out what is going on and variables that the user can see are obviously assigned are not considered assigned. We're highly
|
|
in support of this idea in general, as everyone has run into this at some point or another in their C# careers. The definite assignment
|
|
rules are written in a very syntax-driven form, and thus this proposal is written in a very syntax-driven form to update the relevant
|
|
constructs. Despite that, we do wonder whether we can make these rules more holistic and systematic, such that we don't need to make
|
|
them syntax-specific like they need to be today. We're also less enthused about the conditional expression version. If it fell out of
|
|
more general rules it would be nice, but it's not highly important like the null conditional and coalescing changes seem to be.
|
|
|
|
#### Conclusion
|
|
|
|
The general idea is approved. We'll work to see if we can generalize the rules a bit, and submit a proposal for review on github.
|