Add funcof operator to convert a single-method method group to a Func/Action #1943
Replies: 22 comments
-
What do you propose that the type of
Which immediately falls apart when a function has more than one parameter of the same type, e.g. |
Beta Was this translation helpful? Give feedback.
-
It is I know that C# does not allow the generic type parameter to be open. I am suggesting to add support for this to C# (the CLR also?)
Because the function is of type Maybe this feature should be implemented for non-generic methods first and then for generic methods later. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour , regarding updating C# to allow the generic type parameter to be open: To make things easier, maybe we can have this support only for delegates (variables/expressions whose types are delegates), or maybe even the Func and Action delegates in specific. |
Beta Was this translation helpful? Give feedback.
-
The CLR doesn't support open generic type parameters like that. The bar for modifying the CLR is ridiculously high.
But if the function is of type You can do some degree of currying and partial application with extension methods today. |
Beta Was this translation helpful? Give feedback.
-
Do you mean Also, I am not sure I understand the following part:
|
Beta Was this translation helpful? Give feedback.
-
If the CLR is hard to change, here is some idea that might work:
UPDATE: fixed the sample code above. I originally passed the wrong arguments to func The following type is one of many types that should be part of the BCL:
I am not sure how easy would it be though to write extension methods like |
Beta Was this translation helpful? Give feedback.
-
Oops, I meant Exactly what use cases are there for a feature like this? You claim that it will make functional programming easier, but what does it enable that you can't accomplish today? |
Beta Was this translation helpful? Give feedback.
-
Here is a simple use case:
It enables dependency injection via partial invocation (without using classes). |
Beta Was this translation helpful? Give feedback.
-
Those kinds of scenarios are already pretty easily solved through lamdbas and capturing, with less typing. Action inform = () => InformCustomers((address, subject, body) =>
SendEmail(address, subject, body, "smtp1.local.lab", 25)); |
Beta Was this translation helpful? Give feedback.
-
Also, with your syntax and its dependence on identifying arguments by their type, what would happen if any of the parameters |
Beta Was this translation helpful? Give feedback.
-
@HaloFour , this is only true because the InformCustomers method does not have other parameters. Also
|
Beta Was this translation helpful? Give feedback.
-
@HaloFour , I agree with you that we would have to rely more on parameter types instead of position. Maybe in the future, there would be a way to partially invoke using parameter names. This feature: #259 (comment) using strict Subject = string; |
Beta Was this translation helpful? Give feedback.
-
Why does that matter? You can either have the other parameters become parameters to the List<Customer> customerList = ...;
Action inform = () => InformCustomers((address, subject, body) =>
SendEmail(address, subject, body, "smtp1.local.lab", 25), customerList); Action<List<Customer>> inform = customerList => InformCustomers((address, subject, body) =>
SendEmail(address, subject, body, "smtp1.local.lab", 25), customerList);
Which also makes it intentionally obtuse. |
Beta Was this translation helpful? Give feedback.
-
You added one parameter only. With three it is much longer.
|
Beta Was this translation helpful? Give feedback.
-
Also, can I use |
Beta Was this translation helpful? Give feedback.
-
I don't find that to be a problem.
Nope, for the same reason |
Beta Was this translation helpful? Give feedback.
-
It would. With non-generic methods, If it is generic, with CLR support I think we should be able to use var since it would be translated to Also, with my other suggestion, the type would be |
Beta Was this translation helpful? Give feedback.
-
So
|
Beta Was this translation helpful? Give feedback.
-
It works. It would return Action<..>
Right. Func and Action don't support ref and out, right?
I don't understand this part.
Right. It would only work with single-method method groups. |
Beta Was this translation helpful? Give feedback.
-
Those delegates don't, but other delegates can. There's nothing special about
The problem is that each delegate type is a separate type regardless of it's signature. |
Beta Was this translation helpful? Give feedback.
-
I am specifically proposing that funcof would return Func<..> or Action<..>, not any other type of delegate. If |
Beta Was this translation helpful? Give feedback.
-
If the point is partial application and a currying-like ("like") experience, perhaps something like the following which should be possible purely as compiler transformations.
If there is an overload:
And partially application 'within the same expression' as
Or even if required as an inline parameter:
Allowing a
It could also unify over void methods/Actions.
Useful or 'performant' or not in general? shrug. However it decomposes into a similar manner as some other languages.. The above can currently be handled in C#, albeit requiring the 'long handed' typing. Restrictions:
These restrictions mitigate many (all?) of the issues above around delegates, and using |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Example:
The line that uses the
funcof
operator would be translated to something like:var func = (Func<string, int>)M;
If the following is implemented:
#269
Then the type of the func variable would also contain the parameter names correctly.
The main benefit of such proposal is to be able to treat methods in C# as functions that can then be manipulated (e.g. partially invoked) and passed to other methods. This will make functional programming in C# easier.
Generic Methods
Supporting this proposal for non-generic method should be relatively easy.
I think it would be great to have support also for generic methods. As far as I know, C# currently does not allow a variable type to be an open generic.
For example, given this:
static int M<T>(T p1, string p2) => 1;
funcof(M)
will be of typeFunc<T, string, int>
. C# currently does not support a variable to be of this type (open).If this is possible then we can do something like:
var func = funcof(M).PartiallyInvoke("value for string");
Where
PartiallyInvoke
is a generic user defined method that has many overloads to support partially invoking functions of different number of parameters and different indexes of the parameter to be fixed.func
in this case is of typeFunc<T,int>
. I can invoke it now like this:func(1)
(T is now int)or
func(1u)
(T is now uint)In the example, the PartiallyInvoke method overload is defined like this:
Beta Was this translation helpful? Give feedback.
All reactions