Add LDM notes for Jan. 15, 2020
This commit is contained in:
parent
3bbad41c9c
commit
2d521548ec
159
meetings/2020/LDM-2020-01-15.md
Normal file
159
meetings/2020/LDM-2020-01-15.md
Normal file
|
@ -0,0 +1,159 @@
|
|||
|
||||
# C# Language Design Meeting for Jan. 15th, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
1. Working with data
|
||||
2. Record feature breakdown
|
||||
|
||||
## Discussion
|
||||
|
||||
### Working with data
|
||||
|
||||
As we discuss records, we want to go over a design document we produced a number of years ago
|
||||
called "working with data." This document lays out how, when we design features, we inherently
|
||||
express a "path of least resistance," which consists of the features that seem easiest or
|
||||
shortest to use to accomplish a given problem.
|
||||
|
||||
Link: https://github.com/dotnet/csharplang/issues/3107
|
||||
|
||||
The document argues that, as we find particular patterns to be more effective at building
|
||||
software, we should make the forms we find to be more effective simpler or shorter to express in
|
||||
the language. We should not "change" our opinions, meaning make old syntax illegal, but we should
|
||||
"level the playing field" by making other forms simpler.
|
||||
|
||||
The conclusion of the design document is that we should favor
|
||||
|
||||
1. Immutable members in records by default
|
||||
1. Any features from records that we separate should not make the simple syntax longer
|
||||
|
||||
### Record feature breakdown
|
||||
|
||||
We've also been working on breaking down the individual features
|
||||
of records and determining how independent they can or should be.
|
||||
|
||||
Notes: https://github.com/dotnet/csharplang/issues/3137
|
||||
|
||||
There seem to be the following somewhat separable parts of records
|
||||
|
||||
1. Value-based equality
|
||||
2. Construction boilerplate
|
||||
3. Object initializers
|
||||
4. Nondestructive mutation
|
||||
5. Data-friendly defaults
|
||||
|
||||
#### Value equality
|
||||
|
||||
It's been proposed that a `key` modifier could be applied to signal that value-based equality is
|
||||
being generated based on the members which have it. This works in many cases,
|
||||
but if the absence of the `key` modifier means inherited equality, we're not sure
|
||||
that's the semantics we want. It would also not allow value-based equality to be
|
||||
"specified" in the base class in some sense, enforcing value equality for the deriving
|
||||
type. Whether this is valuable or blocking is an open question.
|
||||
|
||||
#### Construction boilerplate
|
||||
|
||||
Creating a constructor to assign members of a container is one of the largest sources
|
||||
of repetitive boilerplate, e.g.
|
||||
|
||||
```C#
|
||||
public class Point
|
||||
{
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
public Point(int x, int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can imagine various points on this spectrum to simplify the boilerplate,
|
||||
|
||||
```C#
|
||||
public class Point
|
||||
{
|
||||
public key int X { get; }
|
||||
public key int Y { get; }
|
||||
public Point(X, Y); // name matching and type absence implies initialization
|
||||
}
|
||||
```
|
||||
|
||||
Which removes the duplication of naming the same elements multiple times or,
|
||||
|
||||
```C#
|
||||
public class Point(X, Y)
|
||||
{
|
||||
public key int X { get; }
|
||||
public key int Y { get; }
|
||||
}
|
||||
```
|
||||
|
||||
Which removes the constructor name duplication and we could go further to remove
|
||||
property name duplication,
|
||||
|
||||
```C#
|
||||
public class Point(
|
||||
public key int X { get; }
|
||||
public key int Y { get; }
|
||||
);
|
||||
```
|
||||
|
||||
Going all the way to the original position deconstruction
|
||||
|
||||
```C#
|
||||
public class Point(int X, int Y);
|
||||
```
|
||||
|
||||
Where we pick a point in this space seems to correspond to the perceived benefits
|
||||
of the orthogonality of the feature. If the construction shorthand is useful for
|
||||
many scenarios outside of the record scenarios, it's practical to expand it.
|
||||
|
||||
### Object initializers
|
||||
|
||||
One benefit to object initializers is that they don't refer to a constructor directly,
|
||||
only to the properties. This sidesteps a weakness in C#, where constructor initialization in inheritance requires repetition. Without constructors the simple
|
||||
relation
|
||||
|
||||
```C#
|
||||
public abstract class Person
|
||||
{
|
||||
public string Name { get; }
|
||||
}
|
||||
public class Student : Person
|
||||
{
|
||||
public string ID { get;}
|
||||
}
|
||||
```
|
||||
|
||||
has no repetition. Each class states only the properties that are essential, and
|
||||
for derived classes all the base properties are inherited without repetition.
|
||||
Once you add constructors this breaks down
|
||||
|
||||
```C#
|
||||
public abstract class Person
|
||||
{
|
||||
public string Name { get; }
|
||||
public Person(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
public class Student : Person
|
||||
{
|
||||
public string ID { get; }
|
||||
public Student(string id, string name)
|
||||
: base(name)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now the derived classes have to repeat everything from the base, causing brittleness
|
||||
along the boundary. If we were to imagine some improvement to object initializers,
|
||||
then defining a constructor would not be required.
|
||||
|
||||
On the other hand, this also removes one of the main benefits for having a constructor,
|
||||
namely that you can validate the whole state of the object before producing it.
|
|
@ -44,11 +44,6 @@
|
|||
- https://github.com/dotnet/csharplang/issues/3117 Top-level statements and functions (Mads)
|
||||
- https://github.com/dotnet/csharplang/issues/3086 Expressions Blocks (Chuck)
|
||||
|
||||
## Jan 15, 2020
|
||||
|
||||
- Records: Where it fits in our *programming with data* theme (Neal)
|
||||
- Records: The individual subfeatures of records (Mads)
|
||||
|
||||
## Jan 13, 2020
|
||||
|
||||
- Records: Paging back in the previous proposal (Andy)
|
||||
|
@ -57,6 +52,15 @@
|
|||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## Jan 15, 2020
|
||||
|
||||
[C# Language Design Notes for Jan, 2015](LDM-2020-01-15.md)
|
||||
|
||||
Records
|
||||
|
||||
1. "programming with data"
|
||||
1. Decomposing subfeatures of records
|
||||
|
||||
## Jan 8, 2020
|
||||
|
||||
[C# Language Design Notes for Jan 8, 2020](LDM-2020-01-08.md)
|
||||
|
|
Loading…
Reference in a new issue