Add notes for Oct. 28, 2019
This commit is contained in:
parent
3b22aa0b47
commit
61966fed72
113
meetings/2019/LDM-2019-10-28.md
Normal file
113
meetings/2019/LDM-2019-10-28.md
Normal file
|
@ -0,0 +1,113 @@
|
|||
|
||||
# C# Language Design Notes for Oct. 28, 2019
|
||||
|
||||
## Agenda
|
||||
|
||||
1. Discard parameters in lambdas and other methods
|
||||
1. Enhancing the common type algorithm
|
||||
|
||||
## Discussion
|
||||
|
||||
### Discard parameters
|
||||
|
||||
We wanted to talk about discard parameters in lambdas, and also potential expansions into other
|
||||
parameter lists like in local functions and regular methods.
|
||||
|
||||
The first hurdle is whether any form of this feature is worth the complexity. The simplest case
|
||||
is lambdas, because the parameter names are not visible to the caller so they are only visible to
|
||||
the implementation. The alternative to discards is to give throw-away names, like
|
||||
`_1`, `_2`, and `_3`, or to use anonymous method syntax (`delegate { }`) to ignore
|
||||
all parameters.
|
||||
|
||||
As for value, this is a fairly commonly requested requested feature ever since we introduced
|
||||
discards. The cost is increased complexity in the language (understanding that discards are legal
|
||||
as lambda parameters), but there's also an argument that not having the feature causes more
|
||||
complexity in the language. Specifically, the anonymous method syntax is almost entirely obsolete
|
||||
compared to the lambda syntax, but is still commonly used in this exact scenario. If usage of
|
||||
this feature decreases the usage of anonymous method syntax, that could be a decrease in required
|
||||
understanding of the language.
|
||||
|
||||
For discards in local functions and method parameter lists, the cost/value ratio is not nearly as
|
||||
clear. The fundamental limitation is that parameter names for methods and local functions are
|
||||
always public surface area to the caller. We find the cost in complexity in resolving these
|
||||
questions higher than the feature is currently worth. If we find that it becomes a highly desired
|
||||
feature later, we would reconsider this decision.
|
||||
|
||||
Lastly, we had a question of how the scoping would work regarding `_` in both
|
||||
the enclosing scope and inner scope of lambdas.
|
||||
|
||||
```C#
|
||||
void M()
|
||||
{
|
||||
int _ = 0;
|
||||
Action<int, int> a = (_, _) =>
|
||||
{
|
||||
_ = 1; // Is this a discard, or does it capture the local above?
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
We considered various options, like making `_` always be a discard in a lambda body when the
|
||||
lambda parameters are discards, but we have a different precedent for non-lambda
|
||||
scopes like the following:
|
||||
|
||||
```C#
|
||||
void M()
|
||||
{
|
||||
int _ = 0;
|
||||
{
|
||||
_ = 1; // This assigns to the variable _
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We decided a better alternative to making complex scoping rules to prevent confusing code is to
|
||||
push for a warning wave to make using `_` as an identifier a warning. Essentially, if the
|
||||
above behavior is confusing, the confusing aspects are best resolved by always using `_` as a
|
||||
discard, rather than special language rules.
|
||||
|
||||
The scoping behavior is confirmed that multiple `_`s in a lambda parameter list are discards.
|
||||
There are no other modifications to variable scopes i.e., they are not introduced in the lambda
|
||||
body scope, but they also hide nothing from the enclosing scope).
|
||||
|
||||
### Common Type Specification
|
||||
|
||||
Proposal: https://github.com/dotnet/csharplang/issues/2823
|
||||
|
||||
This is revisiting a previous design question around whether to improve the common type
|
||||
specification and also to target type various expressions. In the last discussion we wanted more
|
||||
investigation on the impacts of adding target-typing and the consequences to improving the common
|
||||
type algorithm in the future.
|
||||
|
||||
After investigation, there's a proposal to resolve questions about changing common type inference
|
||||
by looking back to an earlier rule: never infer a type that was not one of the input types. This
|
||||
is a rule that mainly comes from where to draw the line on complexity of type inference.
|
||||
|
||||
This is a simple rule, but it's arguable that there are certain enhancements that don't open up
|
||||
to question the entire space of inference, but still satisfy simple requests, like assuming that
|
||||
null and simple integer types can be inferred as nullable. This would be similar to the language
|
||||
specification for nullable lifting operations on binary operators.
|
||||
|
||||
However, that still leaves the fundamental problem we approached in the beginning: improving
|
||||
inference is a breaking change after target-typing is introduced. The proposal introduced is to
|
||||
not improve type inference in the future and consider this an acceptable outcome, given that
|
||||
target typing would satisfactorily resolve most of the examples given, and potentially in a
|
||||
clearer way than improving the common type algorithm. This would also have the property of
|
||||
preserving the original constraint of the common type algorithm, where no type is inferred that
|
||||
isn't present in any of the inputs.
|
||||
|
||||
The biggest drawback here is that the switch expression and conditional expression would behave
|
||||
differently. The conditional expression would have to preserve the common type algorithm for all
|
||||
places it succeeds, for backwards compatibility.
|
||||
|
||||
One possible way out of this is to separate the notion of common type for backwards
|
||||
compatibility, namely in overload resolution, and the inferred type, as the type used for `var`,
|
||||
where no target type is available. If feasible, this would resolve the issue mentioned at the
|
||||
previous meeting, where we would be unable to improve type inference without creating breaking
|
||||
changes in overload resolution.
|
||||
|
||||
**Conclusion**
|
||||
|
||||
Overall, we're in favor of adding target-typing for these expression forms. We should consider if
|
||||
there's anything more we would like to do to make the switch and conditional expressions more
|
||||
similar.
|
|
@ -37,15 +37,18 @@
|
|||
- [Function Pointer syntax](https://gist.github.com/333fred/c69853d55fba26d92a4d03a19f8e28ab) (Fred)
|
||||
- https://github.com/dotnet/csharplang/issues/2823 Enhancing the Common Type Specification (Neal)
|
||||
|
||||
## Oct 28, 2019
|
||||
|
||||
- https://github.com/dotnet/csharplang/issues/111 Confirm whether discard parameters are allowed in methods and local function, confirm scoping behavior (Julien)
|
||||
- https://github.com/dotnet/csharplang/issues/2823 Enhancing the Common Type Specification (Neal)
|
||||
|
||||
# C# Language Design Notes for 2019
|
||||
|
||||
Overview of meetings and agendas for 2019
|
||||
|
||||
## Oct 28, 2019
|
||||
|
||||
[C# Language Design Notes for Oct 28, 2019](LDM-2019-10-28.md)
|
||||
|
||||
1. Discard parameters in lambdas and other methods
|
||||
1. Enhancing the common type algorithm
|
||||
|
||||
## Oct 23, 2019
|
||||
|
||||
[C# Language Design Notes for Oct 23, 2019](LDM-2019-10-23.md)
|
||||
|
|
Loading…
Reference in a new issue