csharplang/meetings/2020/LDM-2020-12-16.md
2020-12-17 16:51:11 -08:00

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.