introduce native curry functions #2920
-
When digging into functional programming we usually goes through curried functions, and since C# is getting most functional each time, would be nice have a suggar for it become more usual. Usual function: public int Sum(int a, int b, int c) => a + b + c; Proposed syntax for curried functions: public int Sum(int a)(int b)(int c) => a + b + c; Compiler generated code public Func<int, Func<int, Func<int, int>>> Sum => a => b => c => a + b + c; |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments
-
IMO currying and overloading don't mix well within a language. Other .NET languages like F# seem to only permit one or the other in different circumstances. Currying and partial application can definitely be useful, but I feel that they're both generally niche and the language already makes it pretty easy to curry via creating a lambda at the call site which captures specific arguments. Also, the code generation you suggested seems inefficient, requiring 3 allocations and 3 virtual dispatches per call. Languages like Scala, which have a similar syntax, flatten the curried function into a normal function that would take 3 parameters, but allow you to apply the arguments from the first parameter list in order to curry and get back a function. This also makes the feature easier to use from other languages. |
Beta Was this translation helpful? Give feedback.
-
The delegate type public int Sum(ref int a, ref int b) => a + b; |
Beta Was this translation helpful? Give feedback.
-
That seems problematic regardless of whether void Capture()
{
int a = 0;
int b = 0;
var curried = Sum(ref a);
curried(ref b);
} The |
Beta Was this translation helpful? Give feedback.
-
public int Sum(ref int a, ref int b) => a + b; honestly I dont know. I didnt know data generic parameters can't have ref, out, in, modifiers until yesterday. I discovered that after your question, when I decided research about. I just would like to have a more clean way to write curried functions. If one could use var in the cenario bellow, it would to very nice too. Though make var sum = (int a) => (int b) => (int c) => a + b + c; |
Beta Was this translation helpful? Give feedback.
-
Not the syntax, but the curried functionality can be implemented like this: public static class Curried {
public static Func<Tout> Bind<T1, Tout> ( this Func<T1, Tout> self, T1 value )
=> () => self.Invoke( value );
public static Func<T2, Tout> Bind<T1, T2, Tout> ( this Func<T1, T2, Tout> self, T1 value )
=> ( T2 t2 ) => self.Invoke( value, t2 );
public static Func<T2, T3, Tout> Bind<T1, T2, T3, Tout> ( this Func<T1, T2, T3, Tout> self, T1 value )
=> ( T2 t2, T3 t3 ) => self.Invoke( value, t2, t3 );
} |
Beta Was this translation helpful? Give feedback.
-
@Flutterish I have created a lib with a code very similar to yours, providing methods for currying, uncurrying, and partial application with all possible overloads. If someone want to check, here is the repository of Curryfy and its nuget. |
Beta Was this translation helpful? Give feedback.
IMO currying and overloading don't mix well within a language. Other .NET languages like F# seem to only permit one or the other in different circumstances. Currying and partial application can definitely be useful, but I feel that they're both generally niche and the language already makes it pretty easy to curry via creating a lambda at the call site which captures specific arguments.
Also, the code generation you suggested seems inefficient, requiring 3 allocations and 3 virtual dispatches per call. Languages like Scala, which have a similar syntax, flatten the curried function into a normal function that would take 3 parameters, but allow you to apply the arguments from the first para…