-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Anonymous Lambda Invocation #14401
Comments
I just noticed that there's some ambiguity in my examples so question is whether the compiler can look into how it's used and emit the correct delegate? not sure whether it make sense. |
Same problem as inferred lambdas, the compiler can't tell which delegate to use. The compiler has no knowledge of any particular delegate class, including |
@HaloFour So in its current state it's not doable, can't they embody this knowledge into the compiler? I mean I imagine they can run some analysis and know these sorts of things? isn't? |
Probably not, particularly in your case where you're depending on the type being known in order to then resolve extension methods. There's no reason why the compiler would select, say, |
@HaloFour I understand, thanks! :) |
I'm missing something here. In what way is: (() => XmlCommandRootElementConverter.ToCommandModelCollection(null))
.ShouldThrow<ArgumentNullException>(); any different to: XmlCommandRootElementConverter.ToCommandModelCollection(null)
.ShouldThrow<ArgumentNullException>() In other words, what is the lambda doing in your examples, as you appear to be immediately executing them? |
That's not actually true. There is a trick that a number of C# functional-extensions libraries use, of defining static methods that coerce lambdas into a specific type. They can be used to invoke lambdas without assigning them to a variable first. For example, if you nuget my own Succinc<T> package, you can do the following: using static SuccincT.Functional.TypedLambdas;
...
Action(() => Console.WriteLine("Hello World"))(); I haven't supported Console.WriteLine(Func((string name) => $"Hello {name}")("Fred")); I'm still unclear why you'd want to do this though. The intended purpose of these typing functions is to allow the following two lines to be equivalent: Func<string, string> func = name => $"Hello {name}";
var func = Func((string name) => $"Hello {name}"); thus allowing pseudo implicit casting of lambdas and thus |
Related: #3990 |
The difference between this:
And this:
Is that
Well, technically you pass it to a function so you do assign it to a variable but this wasn't really the point, the syntax was more my point here. And yeah I know that trick I also kinda implied it in my post when I wrote the following:
But dunno I thought/hoped like it could be a great idea to avoid all these tricks and have a natural syntax where the dirty tricks are left to the compiler. :) p.s. I'll check the library. :) |
(() => XmlCommandRootElementConverter.ToCommandModelCollection(null))
.ShouldThrow<ArgumentNullException>(); Isn't it clearer to use the extension method as a normal method (in combination with ShouldThrow<ArgumentNullException>(
() => XmlCommandRootElementConverter.ToCommandModelCollection(null)); |
I agree. and I don't see the current position of "The compiler has no knowledge of any particular delegate class, including Action<...> or Func<...>, nor does it treat any particular delegate class differently from any other." (as @HaloFour put it) as a reason not to change this. Add a |
Nope. Even assuming that were possible (which it's not, even with a Given the relatively minor inconvenience caused by much of this I don't see it justifying the massive CLR changes required to implement want you'd like to see to support said language features. |
Interesting point re var f = (int i) => i == 0; I see no reason why the compiler can't implicitly cast this to Anyway, this topic is pretty moot: the language team have ruled out implicitly-typed lambdas, favouring local functions instead, so it's unlikely that what @eyalsk is asking for would ever happen. |
The compiler can quite easily. The simplest way is to create an instance of the target delegate type which targets the I personally like the syntax of inferred lambdas and I'd love to see them added to the language. I'm not opposed to having the compiler more bound to the |
I guess if they are coupling tuples to a specific type, might as well do the same for delegates, lists and dictionaries. |
Ughhh... aside from the general usefulness, or ability to be implemented, that thing looks ugly, not to mention that it's easy to miss in the flurry of parenthesis. It's ugly in js by js standards of uglyness: It should be C# style: |
How does adding |
@DavidArno Separates them visually and makes it clear it's an invocation. |
@sirgru I am pretty sure your style would also be possible. That's not the point here. |
That's purely a matter of opinion. I haven't used So as @dsaf says, your use of the optional |
Given the following:
When you do:
It's actually a syntactic sugar to:
Therefor both of them emits the same IL:
So I really don't understand how style is related to this proposal. |
@eyalsk of course it is a matter of style. |
@sirgru Are you serious?
But it is an option today! Why would it make sense when an instance of a delegate is assigned to a variable to be invoked in both ways and in this case it shouldn't? this would be odd for people that likes parenthesis over |
Disclaimer: I didn't really know how to call it so sorry if the name in the title doesn't make sense. :)
Today, in order to invoke a lambda we must assign it to a variable and finally invoke it through the variable.
Action:
Func:
Finally, If we really want to avoid the extra variable declaration then we can create an instance of the delegate and then invoke it but this syntax is less intuitive and readable and is used less and less as time passes.
So what I'm proposing is to allow the same thing for lambda:
I know that the parenthesis operator is mostly used for casting and function calls but I wonder if it make sense to expand this to allow the examples below to work.
I mean after all this is possible:
Foo(() => Console.WriteLine("Hello World"));
I'm mostly speaking about the simple cases here of
Action
andFunc<T>
as syntactic sugar but maybe it can be extended to support all the variations of these types.Example 1:
Equivalent to:
Example 2:
Equivalent to:
Example 3:
Equivalent to:
Example 4:
Equivalent to:
Why do we need it?
Well, sometimes introducing a variable is completely redundant, the classic example is when you use extension methods like in the FluentAssertions assertion library where it offers some extensions to
Action
andFunc<T>
in order to validate all sorts of things like whether the method throws.One of the issues with a temporary variable is refactoring, when you rename the method let's say I'm calling the variable
toCommandModelCollection
and I'm renaming the method later then I have to rename the variable separately and while it's not a major issue it's still error-prone.The text was updated successfully, but these errors were encountered: