This project is read-only.

Shortcut notation for single-argument lambda expressions

Topics: C# Language Design
Jul 14, 2014 at 8:36 PM
Recently I have been writing a lot of LINQ code of the form...
var results = someEnumerable
    .Where(element => element.SomeBooleanPropertyOrExpression)
    .Select(element => element.SomeTransformationMethod());
...and it occurred to me that single argument lambda expressions of this type could be made more concise with the addition of a simple (IMO) shortcut notation. The notation would consist of omitting the argument name and "=>" token, and substituting a single "." everywhere you would have used "element.". For example, the above code using the proposed notation would look like this...
var results = someEnumerable
    .Where(.SomeBooleanPropertyOrExpression)
    .Select(.SomeTransformationMethod())
The inspiration for this notation came from the very convenient way you can pass the name of a method with signature matching some delegate and have it automatically converted to an instance of that delegate. For example...
// Somewhere in scope...
static string ToStringTransform<T>(T obj) { return obj.ToString(); }
// Then later...
IEnumerable<string> results = someEnumerable
    .Where(/* blah blah */)
    .Select(ToStringTransform);
// Wouldn't it be nice to be able to do .Select(.ToString()) instead?
Because the proposed notation is purely syntactic sugar, you can use it anywhere you would normally use the dot operator. Here are some possible applications
// Instance methods
var results = someEnumerable.Where(.Equals("foobar"));
// equivalent to .Where(element => element.Equals("foobar"));

// Properties
var results = someEnumerable.Select(.FooBarProperty);
// equivalent to .Select(element => element.FooBarProperty);

// Operators
var results = Enumerable.Range(1, 10).Select(.++);
// equivalent to .Select(i => i++);

// Extension methods
var dictionary = Enumerable.Range(1, 10).ToDictionary(., .ToString());
// equivalent to .ToDictionary(key => key, value => value.ToString());
The dictionary creation above shows the only special case, where the dot operator appears by itself. This simply evaluates to the value of the argument without calling any method on it. I see several ways of dealing with this "echoing" special case.
  • Use the single "." syntax as above.
  • Use a ".this" syntax. This is unambiguous (I think) because "this" is not a valid method or property name. I considered a ".value" syntax but A) that would conflict with accessing a property named "value" (sadly legal) and B) its the same length as "i => i".
  • Write an "Echo" extension method like so: T Echo<T>(this T obj) { return obj; }. Then ".Echo()" would give us what we want. Alternatively, make the user write the method themselves if they want to do this.
With regards to type inference, this proposal would require no new capabilities in that regard because it is purely syntactic sugar.

There are two potential issues with this syntax that I can see.
  • It does not allow for explicit specification of the single parameter's type. This means it might not be possible to disambiguate between two methods using this shortcut notation. I considered a couple of ways of supporting explicit specification (for example, "(TypeName)."), but all solutions had their problems and I feel that needing to disambiguate in this way is rare enough that forcing the user to use the currently existing standard lambda syntax is acceptable.
  • It is not immediately clear how this syntax would work for lambda expressions where the body of the lambda is a block of statements rather than a single expression. As with the first issue, a solution to this issue could be found, but IMO the main benefit to the proposed syntax would accrue in the single expression lambdas (sorry, I don't know the exact term the language spec uses for these).
I would appreciate any and all feedback about this idea, particularly in regards to potential drawbacks. Obviously there is very nearly no chance of this even being noticed by a C# language developer, but I thought I might as well share the idea to see what others think about it.