# 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: ``` c# 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 ``` c# 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. ``` c# () 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!). ``` c# () 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: ``` c# var t = (x: 3); var t = (: 3); // yuck! ``` On a deconstruction side: ``` c# (x) = e; (x, (y)) = e; ``` that already means something today. You could do: ``` c# (x: x) = e; (: x) = e; ``` We would have ``` c# 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 ``` c# (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.