108 lines
No EOL
4.2 KiB
Markdown
108 lines
No EOL
4.2 KiB
Markdown
|
|
# C# Language Design Notes for Jan. 22, 2020
|
|
|
|
## Agenda
|
|
|
|
1. Top-level statements and functions
|
|
2. Expression Blocks
|
|
|
|
## Discussion
|
|
|
|
### Top-level statements and functions
|
|
|
|
https://github.com/dotnet/csharplang/issues/3117
|
|
|
|
Three main scenarios:
|
|
|
|
1. Simple programs are simple -- remove the boilerplate for Main
|
|
|
|
2. Top-level functions. Members outside of a class.
|
|
|
|
3. Scripting/interactive. Submission system allows state preservation across evaluations.
|
|
|
|
Unfortunately, some of these proposals interact in difficult ways.
|
|
|
|
If you write
|
|
|
|
```C#
|
|
int x = ...;
|
|
```
|
|
|
|
is `x` now a global mutable variable for the entire program? Or is it a
|
|
local variable in a generated Main method?
|
|
|
|
#### Proposal: Simple programs
|
|
|
|
The proposal is to prioritize (1) and (3) and remove boilerplate, while
|
|
enabling use in scripting/interactive scenarios.
|
|
|
|
To address (1), we would allow a single file in the compilation to contain top-level statements,
|
|
and any file to contain top-level local functions, which would be in scope in all files, but it
|
|
would be an error to refer to them.
|
|
|
|
There's wide consensus that (1) is very useful. There's the case of small programs, where you
|
|
really just want to write a few statements and not have to write the boilerplate of classes and
|
|
Main. It's also a very large learning burden in that just to write "Hello, World" requires
|
|
explaining methods, classes, static, etc.
|
|
|
|
(3) is also important partly because there are a number of products and scenarios
|
|
currently using the scripting system. We should keep that in mind to make sure that
|
|
we don't prevent a large number of use cases from ever using the new system.
|
|
|
|
We think (2) is interesting and worth considering. It may not be the highest priority,
|
|
but we need to make sure we don't rule it out entirely. We also think that if we add
|
|
(1) it seems likely that some people would want (2) much sooner.
|
|
|
|
If we do want to make space for (2) we should make sure to look at lookup rules very carefully.
|
|
The C# lookup rules are very complicated and including new ones for top-level members could
|
|
include subtle ways that change new code.
|
|
|
|
When we designed scripting we had experience that copying back-and-forth from interactive and the
|
|
main program is very useful and important. Because the syntax used here is similar to local
|
|
functions and it's not currently proposed that accessibility modifiers are legal, this would
|
|
create a difference when copying code between standard C# and the interactive dialect, since
|
|
presumably those declarations would now be illegal.
|
|
|
|
#### Block expressions
|
|
|
|
https://github.com/dotnet/csharplang/issues/3137
|
|
|
|
We're revisiting the earlier discussions and there is a proposal for how we could
|
|
make blocks legal as expressions. The proposed precedence would be the lowest
|
|
possible, so many ambiguities or breaking changes would be avoided.
|
|
|
|
Examples:
|
|
|
|
```C#
|
|
var x = { ; 3 }; // int x = 3
|
|
var x = { {} 3 }; // int x = 3
|
|
```
|
|
|
|
Note that a final expression is required, so the `'` or `{}` are necessary as "starting
|
|
statements".
|
|
|
|
The most notable restrictions are that you cannot branch out, meaning that `return`, `yield break`, and `yield return`, and `goto` would be illegal in this proposal.
|
|
|
|
Something which was brought up before is whether to use a "trailing expression" to
|
|
produce a value, or introduce some sort of statement to produce the evaluation
|
|
expression. If we used a `break e;` syntax, the above could look like
|
|
|
|
```C#
|
|
var x = { break 3; };
|
|
```
|
|
|
|
One problem is turning the block into a lambda, where `break` would have to be changed to
|
|
`return`. On the other hand, if this code were introduced directly into the method, `return`
|
|
would actually produce different, valid semantics. `break e;` would be an error in both contexts,
|
|
instead of producing different code.
|
|
|
|
The precedence doesn't have agreement. Some people think that the precedence is
|
|
still too high and that we should almost always require a parenthesized wrapper
|
|
expression, except in specific cases where we think it's clear. Other people think
|
|
that this is too low and they want to use them in more places.
|
|
|
|
**Conclusion**
|
|
|
|
We don't think we have enough information about the restrictions we're working under. One way to
|
|
make progress would be to construct a list of the potential ambiguities in using the `{}` as an
|
|
expression term. |