Replies: 26 comments
-
I don't understand the motivation here. Why would you want to create lambda just to invoke it immediately? Your examples either don't make sense to me (statements that create a function, but never invoke it) or could be simplified by removing the lambda. Also, why do you need new syntax for this in the first place? If you have a helper function like this: static T Invoke<T>(Func<T> f) => f(); Then you can write Example 4 like this: Console.WriteLine(Invoke(() => "foo")); (Your If it's just about saving some typing, then to justify new syntax, I think this would have to be really common, which I don't see how it would be. |
Beta Was this translation helpful? Give feedback.
-
@svick Many times, especially in my unit tests I have extension methods that operates on variations of
The temp variable is completely redundant here so with this proposal you would do this:
Today, 3rd party libs offer helper methods to workaround it but depending on a library just to allow this is a bit too much, sometimes not even possible and creating these helper methods in every project can be painful in terms of maintenance and sometimes it might not be immediately clear what is the purpose of the method so it can actually decrease the legibility of the tests. |
Beta Was this translation helpful? Give feedback.
-
Ah, that makes so much more sense. You want delegate extension methods to be available on method groups/lambdas with compatible signatures. |
Beta Was this translation helpful? Give feedback.
-
@eyalsk I didn't realize this issue is copied from the Roslyn repo: dotnet/roslyn#14401, where some of this discussion already happened. And there's also a proposal specifically about calling extension methods on lambdas: https://github.com/dotnet/roslyn/issues/16105. |
Beta Was this translation helpful? Give feedback.
-
@svick Yeah, I just copied some of the things I thought that were important but I'll revisit this proposal a bit to make it crystal clear. |
Beta Was this translation helpful? Give feedback.
-
@jnm2, @svick I revised the post, I also wrote invoke in few places where I really meant create. |
Beta Was this translation helpful? Give feedback.
-
I still see no benefit to examples 1 thru 4. The example you didn't list in the post, using extension method on lambda without explicitly creating a delegate, is the only thing that makes sense here to me. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Hmm so you're saying you want me to change the examples to something like this? Example 1:
Equivalent to:
|
Beta Was this translation helpful? Give feedback.
-
@eyalsk Yes, that's the only one where I see value. Unless I'm missing something. There's no reason to do this as a statement: You'd be passing it to a parameter which is already typed as a specific delegate, or you'd do There's no reason to do |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Okay, these are great points. I listed all of these examples for completeness but sure I'll modify the post and remove examples 2 and 4. Thanks. :) |
Beta Was this translation helpful? Give feedback.
-
One possible way for "self-invoking" lambda is this: |
Beta Was this translation helpful? Give feedback.
-
@vladd Yes but then why not |
Beta Was this translation helpful? Give feedback.
-
And then, why not |
Beta Was this translation helpful? Give feedback.
-
I believe the proposal here is to modify fourth bullet, below, in the specification for Extension method invocations from
to
I've also heard suggestions recently to include method group conversions and tuple conversions as well. |
Beta Was this translation helpful? Give feedback.
-
@gafter Yes, this is exactly what I was trying to convey. |
Beta Was this translation helpful? Give feedback.
-
@eyalsk Oooh, I just ran into a case where I actually do want the syntax you first proposed, but only because it's async: // On the UI thread.
await Task.WhenAll(
(async () =>
{
var foo = await persistenceProvider.GetFoo();
UpdateFoo(foo.X, foo.Y); // Update UI with foo without waiting for bar
})(),
(async () =>
{
var bar = await persistenceProvider.GetBar();
UpdateFoo(bar.X, bar.Y, bar.Z); // Update UI with bar without waiting for foo
})());
// foo and bar are both finished You can't simply replace this with the Now inserting Plus, this is personal, but I really dislike invoking delegates without writing |
Beta Was this translation helpful? Give feedback.
-
@jnm2 I think that is a good use case for this, though using local functions for the same purpose is not that bad either: async Task GetAndUpdateFoo()
{
var foo = await persistenceProvider.GetFoo();
UpdateFoo(foo.X, foo.Y); // Update UI with foo without waiting for bar
}
async Task GetAndUpdateBar()
{
var bar = await persistenceProvider.GetBar();
UpdateFoo(bar.X, bar.Y, bar.Z); // Update UI with bar without waiting for foo
}
// On the UI thread.
await Task.WhenAll(GetAndUpdateFoo(), GetAndUpdateBar());
// foo and bar are both finished This way is more verbose, but it's also less of a syntax soup. (And I think it also makes the likely bug of calling |
Beta Was this translation helpful? Give feedback.
-
Hehe, that was meant to be an imaginary |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Haha.. I'll add it. ;) |
Beta Was this translation helpful? Give feedback.
-
Well I would say I want anonymous local function. And so I support this feature |
Beta Was this translation helpful? Give feedback.
-
Wouldn't the change in extension methods allow you to create your own set of
|
Beta Was this translation helpful? Give feedback.
-
@NetMage No because what you're proposing has exactly the same drawbacks as the alternative section paragraph 2 that I've written above. |
Beta Was this translation helpful? Give feedback.
-
Given that Invoke can be a generic method I don't think it would be any worse than Func<> has turned out to be. |
Beta Was this translation helpful? Give feedback.
-
@NetMage I don't think that just because the framework provides variations to these types which is basically set of standard types that everyone use today, people need to follow and do that for their own codebases, just because it's the correct solution for a framework doesn't mean it's the correct one for any kind of software and if the language can save us from writing redundant code then there's no reason not to do it, at least in this case. |
Beta Was this translation helpful? Give feedback.
This comment was marked as disruptive content.
This comment was marked as disruptive content.
-
/cc @tannergooding |
Beta Was this translation helpful? Give feedback.
-
Summary
Allow lambdas to be created "without" assigning them to variables.
Motivation
Many times, especially in my unit tests I have extension methods that operate on variations of the types
Action<>
and/orFunc<>
, atm I need to create lambdas and assign them to a temp variable and only then I can call these extension methods as opposed to calling them directly on the lambda expression, it looks like this:The temp variable is completely redundant here so with this proposal we could do the following:
Detailed design
Today, the parenthesis operator is mostly used for casting and function calls so what I'm proposing is to extend this to allow lambdas to be created "without" assigning them to variables.
The compiler would probably need to create this temp variable behind the scene but from the language standpoint, the programmer wouldn't have to declare it.
Example 1:
Equivalent to:
Example 2:
Equivalent to:
Example 3: (thanks to @jnm2)
Drawbacks
Don't think there's any drawbacks.
Alternatives
Declare a variable, create a lambda and assign it to a temp variable.
Create a method with a specific parameter that matches the delegate type you want to use and then pass the lambda to it.
The drawback of creating "dummy" methods such as
Do(() => Console.WriteLine("Hello World"));
is that it can be painful to maintain if you use many variations of these delegate types and sometimes you can't even use 3rd-party libs, depends where you work and/or licenses.Another drawback is that both of the approaches above add redundancy and verbosity and as such they may decrease the legibility of the code.
Create an instance of the delegate type directly.
Known Issues:
Related Topics:
Beta Was this translation helpful? Give feedback.
All reactions