Jump to page: 1 2
Thread overview
Function Currying
Nov 15, 2006
Walter Bright
Nov 15, 2006
Hasan Aljudy
Nov 15, 2006
Brad Roberts
Nov 15, 2006
Hasan Aljudy
Nov 15, 2006
Walter Bright
Nov 15, 2006
Hasan Aljudy
Nov 15, 2006
Bill Baxter
Nov 15, 2006
Bill Baxter
Nov 15, 2006
Knud Sørensen
Nov 15, 2006
Georg Wrede
Nov 15, 2006
David Medlock
Nov 15, 2006
David Medlock
Nov 16, 2006
Bill Baxter
Nov 16, 2006
David Medlock
Nov 16, 2006
Reiner Pope
"true" currying [was: Function Currying]
Nov 15, 2006
Reiner Pope
Nov 16, 2006
Bill Baxter
November 15, 2006
D's tuple support has reached the point where function currying is straightforward. I held off from doing a standard library with these because Tom S's bind library is much more comprehensive, and I hope he'll update it with these.

------ Curry first argument -----------------

R delegate(U) Curry(Dummy=void, R, A, U...)(R function(A, U) dg, A arg)
{
    struct Foo
    {
	typeof(dg) dg_m;
	typeof(arg) arg_m;

	R bar(U r)
	{
	    return dg_m(arg_m, r);
	}
    }

    Foo* f = new Foo;
    f.dg_m = dg;
    f.arg_m = arg;
    return &f.bar;
}

R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg)
{
    struct Foo
    {
	typeof(dg) dg_m;
	typeof(arg) arg_m;

	R bar(U r)
	{
	    return dg_m(arg_m, r);
	}
    }

    Foo* f = new Foo;
    f.dg_m = dg;
    f.arg_m = arg;
    return &f.bar;
}

void main()
{
    static int plus(int x, int y, int z)
    {
	return x + y + z;
    }

    auto plus_two = Curry(&plus, 2);
    printf("%d\n", plus_two(6, 8));
    auto plus_three = Curry(plus_two, 3);
    printf("%d\n", plus_three(7));

    int minus(int x, int y, int z)
    {
	return x + y + z;
    }

    auto minus_two = Curry(&minus, 2);
    printf("%d\n", minus_two(6, 8));
    auto minus_three = Curry(minus_two, 3);
    printf("%d\n", minus_three(7));
}
-------- Curry all the arguments -------------------------

R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args)
{
    struct Foo
    {
	typeof(dg) dg_m;
	U args_m;

	R bar()
	{
	    return dg_m(args_m);
	}
    }

    Foo* f = new Foo;
    f.dg_m = dg;
    foreach (i, arg; args)
	f.args_m[i] = arg;
    return &f.bar;
}

R delegate() CurryAll(R, U...)(R delegate(U) dg, U args)
{
    struct Foo
    {
	typeof(dg) dg_m;
	U args_m;

	R bar()
	{
	    return dg_m(args_m);
	}
    }

    Foo* f = new Foo;
    f.dg_m = dg;
    foreach (i, arg; args)
	f.args_m[i] = arg;
    return &f.bar;
}


void main()
{
    static int plus(int x, int y, int z)
    {
	return x + y + z;
    }

    auto plus_two = CurryAll(&plus, 2, 3, 4);
    printf("%d\n", plus_two());
    assert(plus_two() == 9);

    int minus(int x, int y, int z)
    {
	return x + y + z;
    }

    auto minus_two = CurryAll(&minus, 7, 8, 9);
    printf("%d\n", minus_two());
    assert(minus_two() == 24);
}
-----------------------
November 15, 2006
Is everyone supposed to know what currying means? and what are its uses?

Walter Bright wrote:
> D's tuple support has reached the point where function currying is straightforward. I held off from doing a standard library with these because Tom S's bind library is much more comprehensive, and I hope he'll update it with these.
> 
> ------ Curry first argument -----------------
> 
> R delegate(U) Curry(Dummy=void, R, A, U...)(R function(A, U) dg, A arg)
> {
>     struct Foo
>     {
>     typeof(dg) dg_m;
>     typeof(arg) arg_m;
> 
>     R bar(U r)
>     {
>         return dg_m(arg_m, r);
>     }
>     }
> 
>     Foo* f = new Foo;
>     f.dg_m = dg;
>     f.arg_m = arg;
>     return &f.bar;
> }
> 
> R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg)
> {
>     struct Foo
>     {
>     typeof(dg) dg_m;
>     typeof(arg) arg_m;
> 
>     R bar(U r)
>     {
>         return dg_m(arg_m, r);
>     }
>     }
> 
>     Foo* f = new Foo;
>     f.dg_m = dg;
>     f.arg_m = arg;
>     return &f.bar;
> }
> 
> void main()
> {
>     static int plus(int x, int y, int z)
>     {
>     return x + y + z;
>     }
> 
>     auto plus_two = Curry(&plus, 2);
>     printf("%d\n", plus_two(6, 8));
>     auto plus_three = Curry(plus_two, 3);
>     printf("%d\n", plus_three(7));
> 
>     int minus(int x, int y, int z)
>     {
>     return x + y + z;
>     }
> 
>     auto minus_two = Curry(&minus, 2);
>     printf("%d\n", minus_two(6, 8));
>     auto minus_three = Curry(minus_two, 3);
>     printf("%d\n", minus_three(7));
> }
> -------- Curry all the arguments -------------------------
> 
> R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args)
> {
>     struct Foo
>     {
>     typeof(dg) dg_m;
>     U args_m;
> 
>     R bar()
>     {
>         return dg_m(args_m);
>     }
>     }
> 
>     Foo* f = new Foo;
>     f.dg_m = dg;
>     foreach (i, arg; args)
>     f.args_m[i] = arg;
>     return &f.bar;
> }
> 
> R delegate() CurryAll(R, U...)(R delegate(U) dg, U args)
> {
>     struct Foo
>     {
>     typeof(dg) dg_m;
>     U args_m;
> 
>     R bar()
>     {
>         return dg_m(args_m);
>     }
>     }
> 
>     Foo* f = new Foo;
>     f.dg_m = dg;
>     foreach (i, arg; args)
>     f.args_m[i] = arg;
>     return &f.bar;
> }
> 
> 
> void main()
> {
>     static int plus(int x, int y, int z)
>     {
>     return x + y + z;
>     }
> 
>     auto plus_two = CurryAll(&plus, 2, 3, 4);
>     printf("%d\n", plus_two());
>     assert(plus_two() == 9);
> 
>     int minus(int x, int y, int z)
>     {
>     return x + y + z;
>     }
> 
>     auto minus_two = CurryAll(&minus, 7, 8, 9);
>     printf("%d\n", minus_two());
>     assert(minus_two() == 24);
> }
> -----------------------
November 15, 2006
The net is a truly wonderful resource:

http://en.wikipedia.org/wiki/Curried_function

Hasan Aljudy wrote:
> Is everyone supposed to know what currying means? and what are its uses?
> 
> Walter Bright wrote:
>> D's tuple support has reached the point where function currying is straightforward. I held off from doing a standard library with these because Tom S's bind library is much more comprehensive, and I hope he'll update it with these.
>>
>> ------ Curry first argument -----------------
>>
>> R delegate(U) Curry(Dummy=void, R, A, U...)(R function(A, U) dg, A arg)
>> {
>>     struct Foo
>>     {
>>     typeof(dg) dg_m;
>>     typeof(arg) arg_m;
>>
>>     R bar(U r)
>>     {
>>         return dg_m(arg_m, r);
>>     }
>>     }
>>
>>     Foo* f = new Foo;
>>     f.dg_m = dg;
>>     f.arg_m = arg;
>>     return &f.bar;
>> }
>>
>> R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg)
>> {
>>     struct Foo
>>     {
>>     typeof(dg) dg_m;
>>     typeof(arg) arg_m;
>>
>>     R bar(U r)
>>     {
>>         return dg_m(arg_m, r);
>>     }
>>     }
>>
>>     Foo* f = new Foo;
>>     f.dg_m = dg;
>>     f.arg_m = arg;
>>     return &f.bar;
>> }
>>
>> void main()
>> {
>>     static int plus(int x, int y, int z)
>>     {
>>     return x + y + z;
>>     }
>>
>>     auto plus_two = Curry(&plus, 2);
>>     printf("%d\n", plus_two(6, 8));
>>     auto plus_three = Curry(plus_two, 3);
>>     printf("%d\n", plus_three(7));
>>
>>     int minus(int x, int y, int z)
>>     {
>>     return x + y + z;
>>     }
>>
>>     auto minus_two = Curry(&minus, 2);
>>     printf("%d\n", minus_two(6, 8));
>>     auto minus_three = Curry(minus_two, 3);
>>     printf("%d\n", minus_three(7));
>> }
>> -------- Curry all the arguments -------------------------
>>
>> R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args)
>> {
>>     struct Foo
>>     {
>>     typeof(dg) dg_m;
>>     U args_m;
>>
>>     R bar()
>>     {
>>         return dg_m(args_m);
>>     }
>>     }
>>
>>     Foo* f = new Foo;
>>     f.dg_m = dg;
>>     foreach (i, arg; args)
>>     f.args_m[i] = arg;
>>     return &f.bar;
>> }
>>
>> R delegate() CurryAll(R, U...)(R delegate(U) dg, U args)
>> {
>>     struct Foo
>>     {
>>     typeof(dg) dg_m;
>>     U args_m;
>>
>>     R bar()
>>     {
>>         return dg_m(args_m);
>>     }
>>     }
>>
>>     Foo* f = new Foo;
>>     f.dg_m = dg;
>>     foreach (i, arg; args)
>>     f.args_m[i] = arg;
>>     return &f.bar;
>> }
>>
>>
>> void main()
>> {
>>     static int plus(int x, int y, int z)
>>     {
>>     return x + y + z;
>>     }
>>
>>     auto plus_two = CurryAll(&plus, 2, 3, 4);
>>     printf("%d\n", plus_two());
>>     assert(plus_two() == 9);
>>
>>     int minus(int x, int y, int z)
>>     {
>>     return x + y + z;
>>     }
>>
>>     auto minus_two = CurryAll(&minus, 7, 8, 9);
>>     printf("%d\n", minus_two());
>>     assert(minus_two() == 24);
>> }
>> -----------------------

November 15, 2006

Brad Roberts wrote:
> The net is a truly wonderful resource:
> 
> http://en.wikipedia.org/wiki/Curried_function

I've read that a while ago, but it doesn't make much of a sense. Why would anyone need such a thing?
My original question was, is it something that everyone is supposed to already know its meaning and uses?

> 
> Hasan Aljudy wrote:
>> Is everyone supposed to know what currying means? and what are its uses?
>>
>> Walter Bright wrote:
>>> D's tuple support has reached the point where function currying is straightforward. I held off from doing a standard library with these because Tom S's bind library is much more comprehensive, and I hope he'll update it with these.
>>>
>>> ------ Curry first argument -----------------
>>>
>>> R delegate(U) Curry(Dummy=void, R, A, U...)(R function(A, U) dg, A arg)
>>> {
>>>     struct Foo
>>>     {
>>>     typeof(dg) dg_m;
>>>     typeof(arg) arg_m;
>>>
>>>     R bar(U r)
>>>     {
>>>         return dg_m(arg_m, r);
>>>     }
>>>     }
>>>
>>>     Foo* f = new Foo;
>>>     f.dg_m = dg;
>>>     f.arg_m = arg;
>>>     return &f.bar;
>>> }
>>>
>>> R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg)
>>> {
>>>     struct Foo
>>>     {
>>>     typeof(dg) dg_m;
>>>     typeof(arg) arg_m;
>>>
>>>     R bar(U r)
>>>     {
>>>         return dg_m(arg_m, r);
>>>     }
>>>     }
>>>
>>>     Foo* f = new Foo;
>>>     f.dg_m = dg;
>>>     f.arg_m = arg;
>>>     return &f.bar;
>>> }
>>>
>>> void main()
>>> {
>>>     static int plus(int x, int y, int z)
>>>     {
>>>     return x + y + z;
>>>     }
>>>
>>>     auto plus_two = Curry(&plus, 2);
>>>     printf("%d\n", plus_two(6, 8));
>>>     auto plus_three = Curry(plus_two, 3);
>>>     printf("%d\n", plus_three(7));
>>>
>>>     int minus(int x, int y, int z)
>>>     {
>>>     return x + y + z;
>>>     }
>>>
>>>     auto minus_two = Curry(&minus, 2);
>>>     printf("%d\n", minus_two(6, 8));
>>>     auto minus_three = Curry(minus_two, 3);
>>>     printf("%d\n", minus_three(7));
>>> }
>>> -------- Curry all the arguments -------------------------
>>>
>>> R delegate() CurryAll(Dummy=void, R, U...)(R function(U) dg, U args)
>>> {
>>>     struct Foo
>>>     {
>>>     typeof(dg) dg_m;
>>>     U args_m;
>>>
>>>     R bar()
>>>     {
>>>         return dg_m(args_m);
>>>     }
>>>     }
>>>
>>>     Foo* f = new Foo;
>>>     f.dg_m = dg;
>>>     foreach (i, arg; args)
>>>     f.args_m[i] = arg;
>>>     return &f.bar;
>>> }
>>>
>>> R delegate() CurryAll(R, U...)(R delegate(U) dg, U args)
>>> {
>>>     struct Foo
>>>     {
>>>     typeof(dg) dg_m;
>>>     U args_m;
>>>
>>>     R bar()
>>>     {
>>>         return dg_m(args_m);
>>>     }
>>>     }
>>>
>>>     Foo* f = new Foo;
>>>     f.dg_m = dg;
>>>     foreach (i, arg; args)
>>>     f.args_m[i] = arg;
>>>     return &f.bar;
>>> }
>>>
>>>
>>> void main()
>>> {
>>>     static int plus(int x, int y, int z)
>>>     {
>>>     return x + y + z;
>>>     }
>>>
>>>     auto plus_two = CurryAll(&plus, 2, 3, 4);
>>>     printf("%d\n", plus_two());
>>>     assert(plus_two() == 9);
>>>
>>>     int minus(int x, int y, int z)
>>>     {
>>>     return x + y + z;
>>>     }
>>>
>>>     auto minus_two = CurryAll(&minus, 7, 8, 9);
>>>     printf("%d\n", minus_two());
>>>     assert(minus_two() == 24);
>>> }
>>> -----------------------
> 
November 15, 2006
Hasan Aljudy wrote:
> 
> 
> Brad Roberts wrote:
>> The net is a truly wonderful resource:
>>
>> http://en.wikipedia.org/wiki/Curried_function
> 
> I've read that a while ago, but it doesn't make much of a sense. Why would anyone need such a thing?
> My original question was, is it something that everyone is supposed to already know its meaning and uses?

It's handy when you want to 'save' a command for future use, such as pushing it onto an undo/redo stack. Being able to encapsulate the arguments into just a function call make this particularly useful.
November 15, 2006

Walter Bright wrote:
> Hasan Aljudy wrote:
>>
>>
>> Brad Roberts wrote:
>>> The net is a truly wonderful resource:
>>>
>>> http://en.wikipedia.org/wiki/Curried_function
>>
>> I've read that a while ago, but it doesn't make much of a sense. Why would anyone need such a thing?
>> My original question was, is it something that everyone is supposed to already know its meaning and uses?
> 
> It's handy when you want to 'save' a command for future use, such as pushing it onto an undo/redo stack. Being able to encapsulate the arguments into just a function call make this particularly useful.

Hmm, sounds legitimate but I still don't quiet get it. Can you give a more concrete example?
I mean, I can always save a command using a nested function. Why would I choose to call a curry template for something like, say:

void func( type arg )
{
    doSomething(arg);
    ......
    doSomething(arg);
    ..
    doSomething(arg);
    ..
    doSomething(arg);

    //I'm tired of this ..
    //call nested functions to the rescue ..
    void doit()
    {
        doSomething(arg);
    }

    doit();
    doit();
    ...
    doit();
}

I'm more confident using a nested function, at least I know what's going on. With a curried function, I'd be more like "gee I'm not sure what's going on but I hope this works ..".
November 15, 2006
"Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message news:eje8hg$10on$1@digitaldaemon.com...
>
> Hmm, sounds legitimate but I still don't quiet get it. Can you give a more
> concrete example?
> I mean, I can always save a command using a nested function. Why would I
> choose to call a curry template for something like, say:
>
> void func( type arg )
> {
>     doSomething(arg);
>     ......
>     doSomething(arg);
>     ..
>     doSomething(arg);
>     ..
>     doSomething(arg);
>
>     //I'm tired of this ..
>     //call nested functions to the rescue ..
>     void doit()
>     {
>         doSomething(arg);
>     }
>
>     doit();
>     doit();
>     ...
>     doit();
> }
>
> I'm more confident using a nested function, at least I know what's going on. With a curried function, I'd be more like "gee I'm not sure what's going on but I hope this works ..".

Go ahead and try to return doit() from func(), or save it somewhere where it will be accessed after func() returns ;)  I mean, you _could_ do it without templates using a struct as the context (much as Walter's posted code does), but you'd be seriously restricting yourself to functions/delegates with certain signatures.


November 15, 2006
Hasan Aljudy wrote:
> 
> 
> Brad Roberts wrote:
>> The net is a truly wonderful resource:
>>
>> http://en.wikipedia.org/wiki/Curried_function
> 
> I've read that a while ago, but it doesn't make much of a sense. Why would anyone need such a thing?
> My original question was, is it something that everyone is supposed to already know its meaning and uses?

Yes, if you've been through a decent CS undergrad program you should probably at least have a vague idea what it is.  It's more common in functional languages (which should also be part of a decent undergrad curriculum).

Although apparently confusion over what's "currying" and what's "partial function evaluation" abounds.

The difference as I understand it is that 'currying' is supposed to create a new function that takes one parameter and returns a function of one less parameter.  So curried_add, a curried version of add(a,b,c), could be called like curried_add(a)(b)(c).  So the thing that 'curries' add() should just take 'add' as a paramter:  curried_add = curry(add). The key is that when you're currying, nothing is actually evaluated. curried_add still does everything the original function did.

Partial evaluation is when you actually reduce the number of arguments by one or more, by 'baking them in'.  Like in Walter's examples.  So the examples are actually showing partial evaluation, not currying.

As for usefulness... one use case is similar to delegates.  If you have some function like do_something(Object, argument), with partial evaluation you can create a new function do_something_to_object(argument), where the object doesn't have to be supplied.  And since you can repeat the process for any number of arguments you can have something like a delegate that contains N implicit .ptr values rather than just one.

Functional language folks are crazy about it.  ML doesn't actually even have multi-argument functions.  Every function is always fully curried, so every function takes at most 1 argument.  If it appears to take 2 arguments like "add a b", it's a disguise.  'add' really takes 1 argument, and returns another function of 1 argument, which then takes the second argument, and finally returns a value.

It would be interesting to see if you could actually make a real 'curry' function.  One that takes a function, foo(a,b,c,d) of N arguments and returns a cascaded set of functions with 1 argument each that you can call like curried_foo(a)(b)(c)(d).  It should be doable with some sort of recursive template.


--bb
November 15, 2006
On Tue, 14 Nov 2006 20:07:41 -0800, Brad Roberts wrote:

> The net is a truly wonderful resource:
> 
> http://en.wikipedia.org/wiki/Curried_function
> 

someone should add a D example to that wiki page.


November 15, 2006

Knud Sørensen wrote:
> On Tue, 14 Nov 2006 20:07:41 -0800, Brad Roberts wrote:
> 
> 
>>The net is a truly wonderful resource:
>>
>>http://en.wikipedia.org/wiki/Curried_function
>>
> 
> 
> someone should add a D example to that wiki page.

Yeah, but it better not just show partial function evaluation!!
« First   ‹ Prev
1 2