Add LDM notes for Feb 26, 2020
This commit is contained in:
parent
cf22e016c7
commit
1dbb8e82be
123
meetings/2020/LDM-2020-02-26.md
Normal file
123
meetings/2020/LDM-2020-02-26.md
Normal file
|
@ -0,0 +1,123 @@
|
|||
|
||||
# C# Language Design Meeting for Feb. 26, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
Design Review
|
||||
|
||||
## Discussion
|
||||
|
||||
Today is a design review, where we collect the design team, selected emeritus
|
||||
members, and a number of broad ecosystem experts to provide some "in-the-moment"
|
||||
feedback to our current designs and their directions.
|
||||
|
||||
Today we presented more of our thoughts on the top-level statements/"simple programs"
|
||||
features and records.
|
||||
|
||||
### Simple Programs
|
||||
|
||||
We have a prototype of simple programs. As per the existing spec, you can have
|
||||
top-level functions among all files, and other statements in a single file.
|
||||
|
||||
Collected feedback, not in any particular order:
|
||||
|
||||
* Supporting local functions in files other than the top-level statement file doesn't
|
||||
seem useful and could cause confusion. If there's a local function defined in a file
|
||||
only with classes, it would appear that that function would be in scope for the
|
||||
classes, according to C# lexical scoping conventions. However, since these are defined
|
||||
as *local functions*, not top-level methods, it would be an error to use them inside
|
||||
the class. Moreover, even if that confusion is resolved, there doesn't seem to be a
|
||||
compelling reason to allow it in the first place. Because these functions are not
|
||||
accessible from anything except the main statement file, it would be most likely to
|
||||
want to put the functions in that file, next to the uses. The only benefit from allowing
|
||||
local functions in separate file may be as a helper file that is linked into other
|
||||
compilations. However, wrapping these utility functions in a class so they can be used
|
||||
in more places seems like a small burden with big benefits. Once wrapped in a class,
|
||||
these functions are simply methods like in C# today.
|
||||
|
||||
* Mixing classes and statements in the same file could generate some confusion. The existing
|
||||
design is that classes can see the variables created by statements, but it would be illegal
|
||||
to reference them. This keeps the option open to allow access later. However, this could be
|
||||
a confusing middle ground. To simplify the situation we could require only statements in the
|
||||
top-level in one file (forcing all types to be declared in separate files). However, there is
|
||||
interest in using utility classes in the top-level statements, perhaps especially with a
|
||||
forthcoming records feature that provides simple, short syntax for declaring new types.
|
||||
|
||||
* Many of these features mirror what we already have in CSX. It's good that our
|
||||
current designs are similar and allow these constructs in more places, but since the semantics of
|
||||
this design have subtle differences from CSX this would effectively create a third dialect of C#.
|
||||
There's some desire to unify these worlds, but it's difficult. CSX is designed to allow all
|
||||
values to be persisted, which is important for the scripting "submission" system, but this makes
|
||||
a number of types of statements illegal that we have support for in the current design, like
|
||||
ref locals. It also creates a burden for new designs, where statements need to be explicitly
|
||||
designed for both CSX and C#. For example, the new `using var` declaration form is nonsensical
|
||||
under the CSX design and probably should be illegal. Since the current 'simple programs' design
|
||||
effectively treats statements like they are part of a method body, there's a cleaner semantic
|
||||
parallel with C#, meaning less special-casing.
|
||||
|
||||
### Records
|
||||
|
||||
Here we presented a variety of different pieces of designs we have been thinking about.
|
||||
|
||||
#### Nominal Record
|
||||
|
||||
Feedback:
|
||||
|
||||
* One of the biggest drawbacks of the current writeable-property style in C#, where types are
|
||||
declared with public mutable properties that are then initialized using object initializers,
|
||||
is that author can't enforce that certain properties are always initialized. It would be a
|
||||
big disappointment if any "nominal records" feature that we built couldn't support this feature.
|
||||
|
||||
* With the design as-is there's no way to validate the whole state of the object. However, that's
|
||||
also true of the object-initializer style currently in use, and this doesn't seem to be as a big
|
||||
of a problem for current users.
|
||||
|
||||
#### Value Equality
|
||||
|
||||
* Positive feelings on generating `.Equals(T)` and implementing `IEquatable<T>`, mixed feelings
|
||||
on generating the `==` and `!=` operators.
|
||||
|
||||
* If we opt-in the whole class using `value class`, we also need an opt-out for individual members.
|
||||
Regular classes also often have somewhat specialized equality requirements, like wanting to compare
|
||||
certain lists as sequence-equal, or compare strings ignoring case. This observation points to a
|
||||
lot more customization points for value equality on general classes than value equality on records.
|
||||
|
||||
* Using value equality on mutable state is seems dangerous if the type is used in a dictionary,
|
||||
but despite the danger, other languages (Java, Go) have value equality for common types, like
|
||||
lists, that can be easily added to a dictionary.
|
||||
|
||||
* We don't currently have a robust mental model for what it means to be a "value class." Is "value
|
||||
class" a separable concept from "implementing value equality," which people often do today? Or
|
||||
is it not a different type of class, but simply a modifier signaling an implementation detail,
|
||||
namely that the compiler generates value equality automatically. If we think of value equality
|
||||
as a public contract, how does that change our view of existing code? Classes can currently
|
||||
override Equals, but we don't distinguish what *kind* of Equals they provide. That isn't a
|
||||
language concept, in a sense, but a part of the documentation.
|
||||
|
||||
### Nominal Records
|
||||
|
||||
* When using the `with` expression on nominal records, the generated parameter-less `With` method
|
||||
looks a lot like `Clone`. It does little aside from return a new object with a shallow copy of
|
||||
the state. If `With` is essentially Clone, why not use one of the existing forms of Clone that we
|
||||
already have?
|
||||
|
||||
* ICloneable is deprecated and MemberwiseClone is protected. Maybe we should just call the method
|
||||
Clone(), but not override or implement any of the other framework uses.
|
||||
|
||||
* This feature looks a lot like structural typing from other languages, like Javascript's "spread"
|
||||
operator, but that is not the feature we're currently trying to build. This is feature is still
|
||||
about declaring new types, not providing some compatibility between existing types.
|
||||
|
||||
* We spent a lot of time talking about validation and "validators", a very recent concept that was
|
||||
floated as an alternative to constructors, executing after the `with` expression.
|
||||
|
||||
* There's some general concern about having no capability of validation, but no consensus on
|
||||
exactly how validators should work.
|
||||
|
||||
* If validators work against the copied fields of the object, that seems to imply that the
|
||||
fields are the state being operated on. On the other hand, only certain members can be
|
||||
mentioned in the `with` expression. Why wouldn't those be the things that are copied? Instead
|
||||
of all the state?
|
||||
|
||||
|
||||
|
|
@ -54,10 +54,6 @@
|
|||
- Digest feedback from design review
|
||||
- Records design (Mads, Andy)
|
||||
|
||||
## Feb 26, 2020
|
||||
|
||||
- Design review
|
||||
|
||||
## Jan 29, 2020
|
||||
|
||||
- Records: drilling in to individual features (Mads)
|
||||
|
@ -70,6 +66,12 @@
|
|||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## Feb 26, 2020
|
||||
|
||||
[C# Language Design Notes for Feb. 26, 2020](LDM-2020-02-26.md)
|
||||
|
||||
Design Review
|
||||
|
||||
## Feb 24
|
||||
|
||||
[C# Language Design Notes for Feb. 24, 2020](LDM-2020-02-24.md)
|
||||
|
|
Loading…
Reference in a new issue