csharplang/meetings/2017/LDM-2017-03-15.md
2018-01-25 13:11:49 -08:00

4.2 KiB

C# Language Design Notes for Mar 15, 2017

Quote of the Day: "Little leek - isn't that called a spring onion?" Quote of the Other Day: "Who's champion for recursive patterns? It says 'see champion for recursive patterns'."

Agenda

Triage of championed features

  1. JSON literals
  2. Fixing of captured locals
  3. Allow shadowing of parameters
  4. Weak delegates
  5. Protocols/duck typing/concepts/type classes
  6. Zero and one element tuples
  7. Deconstruction in lambda parameters
  8. Private protected

JSON literals

No

Fixing of captured locals

Not worth any effort, probably even as up for grabs

Allow shadowing of parameters

Current rule saves your bacon a couple of times:

var t = FooAsync(...)

t.ContinueWith(t => ... ); // whoops

Discards would make this worse, in a sense, because they lead people to be more likely to capture.

Shadowing could be used to avoid capturing, but that would be better served by a non-capture feature. Could be a static on lambdas to avoid capture - or it could be a capture list approach.

"Capture nothing", "capture what I want", "capture this" are three potential levels with different cost.

Could be this, static and nothing in front of the lambda. But it might be nice to have an explicit annotation for the default, for people who care to express that they explicitly thought about it.

Individual items in a capture list are worthless if you don't care about different kinds of capture for a given variable.

Also a great candidate for custom annotations so we don't put it in the language. That would also allow folks that want more detail to have that.

Attributes on lambdas seem like a more general feature. Let's feed this in as a scenario for attributes on lambdas.

Weak delegate

Best approach is the small leak pattern which creates a wrapper delegate with a weak reference to the original receiver. That doesn't solve the whole problem, though - how about unregistering, etc?

This isn't necessarily a language feature. This should be a library that you pass the method to, and it wraps it. It would be helped by the language allowing for a delegate constraint.

Conclusion: Not as a language feature right now; figure it out as a library feature, and maybe, someday we would add syntax around it.

Protocols/duck typing/concepts/type classes

More dynamic or more static approaches to "adding a 'type' after the fact".

A separate important subissue is the dependency explosion.

Different solutions to the same problem. They should be addressed as one design effort.

8.0 as a milestone is probably crazy and unrealistic, but helps us prioritize investigation work

Zero and one element tuples

var () = e;       // who cares to deconstruct?
var (x) = e;      // just get through property?
var (x, (y)) = e; // recursive - can't just grab a member

In other languages () are list-like unit type things - an alternative to void, that is more of a first class type and can therefore be used in generics.

() M(...) => (); // returns zero things

Also if we ever embrace bool-returning Deconstruct methods (or the like), you might want zero-length decontructors to mean "there wasn't anything".

Womples (one-element tuples) are more likely to be useful, especially for deconstruction. But they are also the ones that clash most fiercely with existing syntax (parenthesized expressions!).

() t = ();
(int x) = (5);
(int x) = (d); // could go either way - deconstruct a womple, or deconstruct d?

Probably not that useful to have womple expressions. Could allow using named element(s) or even : alone:

var t = (x: 3);
var t = (: 3); // yuck!

On a deconstruction side:

(x) = e;
(x, (y)) = e;

that already means something today. You could do:

(x: x) = e;
(: x) = e;

We would have

if (o is OneDPoint(3)) ...
if (odp is (3)) ...

Open questions abound.

Deconstruction in lambda parameters

It's a special case of deconstruction in parameters

(var (x, y)) => x + y;
double M((int x1, int y1), (int x2, int y2)) => Sqrt(x1 * x2 + y1 * y2);

private protected

Would not use so much in the BCL, but in APIs with deeper hierarchies, definitely.