i am reading Accelerated C# i don't really understand the following code:
public static Func<TArg1, TResult> Bind2nd<TArg1, TArg2, TResult> (
this Func<TArg1, TArg2, TResult> func,
TArg2 constant )
{
return (x) => func( x, constant );
}
in the last line what is x referring to? and there's another:
public static Func<TArg2, Func<TArg1, TResult>> Bind2nd<TArg1, TArg2, TResult>
( this Func<TArg1, TArg2, TResult> func )
{
return (y) => (x) => func( x, y );
}
How do i evaluate this? (y) => (x) => func( x, y )
what is passed where ... it does confusing.
Currying simply means breaking up a Lambda expression so that it accepts up to one input and has up to one output. Each input and expression calculates one part of the solution, and the output from that Lambda expression is an input to the next Lambda expression in the chain.
Currying is the transformation of a function with multiple arguments into a sequence of single-argument functions. That means converting a function like this f(a, b, c, ...) into a function like this f(a)(b)(c)... . If you know Python's functools. partial , then this is very similar to it.
Simple answer. Currying: Lets you call a function, splitting it in multiple calls, providing one argument per-call. Partial Application: Lets you call a function, splitting it in multiple calls, providing multiple arguments per-call.
Curry functions are neat when used to carry containers of reusable code. Basically you take a function with multiple arguments and you know that one of those arguments will have specific value but the other is undecided.
Let's first simplify the code:
Func<int, int> B(Func<int, int, int> f, int c)
{
return x=>f(x, c);
}
This is just the same as:
class Locals
{
public int c;
public Func<int, int, int> f;
public int Magic(int x) { return f(x, c); }
}
Func<int, int> B(Func<int, int, int> f, int c)
{
Locals locals = new Locals();
locals.f = f;
locals.c = c;
return locals.Magic;
}
Now is it clear what x refers to? x is the parameter to function "Magic".
Now you can use B like this:
Func<int, int, int> adder = (a, b)=>a+b;
Func<int, int> addTen = B(adder, 10);
int thirty = addTen(20);
Make sense? See what is happening here? We're taking a function of two parameters and "fixing" one of the parameters to a constant. So it becomes a function of one parameter.
The second example takes that one step further. Again, simplify to get rid of the cruft so that you can understand it more easily:
Func<int, Func<int, int>> B2(Func<int, int, int> f)
{
return y=>x=>f(x,y);
}
This is the same as
class Locals3
{
public int y;
public int Magic3(int x)
{
return x + this.y;
}
}
class Locals2
{
public Func<int, int, int> f;
public Func<int, int> Magic2(int y)
{
Locals3 locals = new Locals3;
locals.y = y;
return locals.Magic3;
}
}
Func<int, Func<int, int>> B2(Func<int, int, int> f)
{
Locals2 locals = new Locals2();
locals.f = f;
return locals.Magic2;
}
So you say
Func<int, int, int> adder = (a, b)=>a+b;
Func<int, Func<int, int>> makeFixedAdder = B2(adder);
Func<int, int> add10 = makeFixedAdder(10);
int thirty = add10(20);
B is a parameter fixer. B2 makes a parameter fixer for you.
However, that's not the point of B2. The point of B2 is that:
adder(20, 10);
gives the same result as
B2(adder)(20)(10)
B2 turns one function of two parameters into two functions of one parameter each.
Make sense?
x is the parameter of the lambda, it is of type TArg1.
It can be helpful to pronounce the => as "maps to" as in "x maps to a new function with a constant of type TArg2 substituted into the original function delegate, func."
The variable x is an unbound variable. That represents an argument to the returned function from calling Bind2nd
.
A few hours with Scheme would help you here, but try this.
When you call Bind2nd
the returned result is a function. That function is defined as
(x) => func (x, constant)
Now that you have the above assigned to a variable, lets say lambda
, you can call that function via the lambda
variable
lambda(x);
The x
defined in Bind2nd
is just a variable that represents an argument to the function that will be returned to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With