question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Lambdas omitting parameters

See original GitHub issue

I often have the situation of functions taking a lambda-expression as a parameter which take a handful of parameters themselves. Something like this:

someFunction((foo, bar, thing, another) => ..);

Of course, delegates with many parameters are often an indicator of bad design, and should be avoided. But it’s the same with fewer arguments.

A situation like the above get’s quite painful if the lambda-body does not even need all those parameters (or is in extreme always returning the same, constant value). But still, the compiler requests me to find unique names for each of the parameters. This is a problem especially when renaming / adding variables “above” the anonymous function which do then interfere with the unused variables there.

Most of the time what I do today is something like this:

someFunction((_, foobar) => ..); //Using '_' as a variable name somewhere around is highly unlikely
someFunction((a, foobar) => ..); //Using short variable names elsewhere is highly unlikely

It also helps reading the code, because I can save a few characters (getting more ‘good’ code into a line) and make it obvious for readers which variables are important to me, making the code more understandable.

Of course this is somewhat limited, because my “placeholders” are really just ordinary names which must not reoccur. This might lead to something like (_, __, foobar, ___) => .. which starts to look ugly again.

I would like it to have _ (or just another special character, for backwards-compatibility) not usable for ordinary variable names and forbid it’s actual usage inside the lambda-body. Therefore it could be used as a real placeholder, enabling something like this:

someFunction((_, _, foobar) => ..);

or even this:

someFunction((foo, _, bar) => bar.otherFunction((_) => foo));

Does this sound like a useful thing to you?

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Reactions:3
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
HaloFourcommented, Jan 17, 2015

A wildcard character had been described in the C# Pattern Matching proposal which may be up for further discussion for C# 7.0. That character was * which does make more sense as _ is considered a valid C# identifier.

How about also allowing skipping multiple arguments?

void Foo(Func<string, int, bool, DateTime, decimal> func) { ... }

Foo(delegate { return 0m; }) // already valid C# 2.0+
Foo((*) => 0m); // shorthand for above
Foo((s, i, *) => 0m); // capture first two args, skip the rest

If there are overloads which accept Func<>s of differing numbers of arguments the overload resolution would select the one with the fewest remaining parameters:

void Foo(Func<string, int, bool, DateTime, decimal> func) { ... }
void Foo(Func<string, int, bool, byte, DateTime, decimal> func) { ... }

Foo((s, i, *) => 0m); // calls the first Foo
Foo((s, i, *, *, *) => 0m); // calls the second Foo

The one issue here, which also affects normal lambdas, is if there are overloads which accept a delegate with the same number of arguments but only differ by the type of those arguments. The only solution that I can think of there is to require specifying the type of the parameter in the lambda, but that makes the entire concept of catching multiple arguments feel weird.

void Foo(Func<string, int, bool> func) { ... }
void Foo(Func<string, string, bool> func) { ... }
void Foo(Func<string, string, int, bool> func) { ... }

Foo((s, int *) => true); // calls first Foo
Foo((s, string *) => true); // calls second Foo
Foo((s, string *, *) => true); // calls third Foo, but ewww

I think that a wildcard would be useful in a number of other scenarios as well, like the following:

string s = ...;
if (int.TryParse(s, out *)) {
    // Don't need the parsed value, no need to declare an extra variable
}
1reaction
MadsTorgersencommented, Aug 15, 2016

This should be thought of as a special case of allowing deconstruction in parameter position, which is something we will consider down the line.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The validity of lambda expression with omitted parameter ...
A lambda-declarator could start with (parameter-declaration-clause) but we don't have that, so we're just looking for lambda-specifiers.
Read more >
Lambda expressions (since C++11)
2) Omitted parameter list: function takes no arguments, as if the parameter list were () . 3) Same as (1), but specifies a...
Read more >
High-order functions and lambdas
When a lambda has parameters, they go first, followed by '->' ... as in () -> A . The Unit return type cannot...
Read more >
Lambda discard parameters - C# 9.0 draft feature ...
This feature specification describes the new language rules that enable the '_' to be a discard parameter in a lambda expression.
Read more >
A pitfall with multiple default function arguments and ...
… Such syntax is also known as trailing lambda. If the lambda is the only argument to that call, the parentheses can be...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found