Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help understanding lambda (currying)

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.

like image 971
Jiew Meng Avatar asked Sep 02 '10 05:09

Jiew Meng


People also ask

What is currying in Lambda?

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.

How do you use currying function?

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.

What is the difference between currying and partial application?

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.

Can you give an example of a curry function and why this syntax offers an advantage?

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.


3 Answers

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?

like image 194
Eric Lippert Avatar answered Oct 04 '22 09:10

Eric Lippert


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."

like image 29
marr75 Avatar answered Oct 04 '22 09:10

marr75


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.

like image 28
linuxuser27 Avatar answered Oct 04 '22 08:10

linuxuser27