Discussion:
Curry and uncurry
Arnar Birgisson
2008-12-17 16:22:53 UTC
Permalink
One thing I think could be useful is to port Haskell's curry and
uncurry. This is basically a convenience method for (un)wrapping an
.apply on a function object:

function curry(f) {
return function () {
// first convert arguments to a regular array
var args = Array.prototype.slice.call(arguments);
return f(args);
}
}

function uncurry(f) {
return function (args) {
return f.apply(this, args);
}
}

Example use:
test = [ [10, 1],
[20, 2],
[30, 3] ];

assertEqual(map(uncurry(operator.plus), test), [11, 22, 33]);

// assume join is a function that takes a list and returns a string
// with the elements joined with some delimiter

f = curry(partial(join, _, ", "))
assert(f("Bond", "James Bond") == "Bond, James Bond")

Does anyone else think this could be useful? What module would it fit?
Base already has a lot of functional stuff (compose, partial, map &
friends) - I'm wondering if it fits there or if all the functional
stuff should be in a seperate module MochiKit.Functional - as Python
seems to be heading.

cheers,
Arnar

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Amit Mendapara
2008-12-18 05:15:04 UTC
Permalink
I think, for functional programming, we should keep things simple.
It's better to keep code simple and readable. Can you explain few more
use cases of the proposed functions?

Regards
--
Amit
Post by Arnar Birgisson
One thing I think could be useful is to port Haskell's curry and
uncurry. This is basically a convenience method for (un)wrapping an
function curry(f) {
    return function () {
        // first convert arguments to a regular array
        var args = Array.prototype.slice.call(arguments);
        return f(args);
    }
}
function uncurry(f) {
    return function (args) {
        return f.apply(this, args);
    }
}
test = [ [10, 1],
         [20, 2],
         [30, 3] ];
assertEqual(map(uncurry(operator.plus), test), [11, 22, 33]);
// assume join is a function that takes a list and returns a string
// with the elements joined with some delimiter
f = curry(partial(join, _, ", "))
assert(f("Bond", "James Bond") == "Bond, James Bond")
Does anyone else think this could be useful? What module would it fit?
Base already has a lot of functional stuff (compose, partial, map &
friends) - I'm wondering if it fits there or if all the functional
stuff should be in a seperate module MochiKit.Functional - as Python
seems to be heading.
cheers,
Arnar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Per Cederberg
2008-12-18 07:31:53 UTC
Permalink
The names "curry" and "uncurry" were a bit confusing to me, so it took
me a while to understand these two functions...

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

To me (and probably other non-Haskell users) the names imply the same
thing as bind or partial. It's a confusing world... :-(

In JavaScript, I think plain apply + MochiKit.Base.bind does the same thing:

var test = [ [10, 1], [20, 2], [30, 3] ];
var addArray = bind("apply", operator.add, null);
assertEqual(map(addArray, test), [11, 22, 33]);

It's no beauty, so perhaps this particular variant of bind merits an
alias? Uncurrying is just the same as the built-in apply function, so
that seems unnecessary.

Cheers,

/Per
Post by Arnar Birgisson
One thing I think could be useful is to port Haskell's curry and
uncurry. This is basically a convenience method for (un)wrapping an
function curry(f) {
return function () {
// first convert arguments to a regular array
var args = Array.prototype.slice.call(arguments);
return f(args);
}
}
function uncurry(f) {
return function (args) {
return f.apply(this, args);
}
}
test = [ [10, 1],
[20, 2],
[30, 3] ];
assertEqual(map(uncurry(operator.plus), test), [11, 22, 33]);
// assume join is a function that takes a list and returns a string
// with the elements joined with some delimiter
f = curry(partial(join, _, ", "))
assert(f("Bond", "James Bond") == "Bond, James Bond")
Does anyone else think this could be useful? What module would it fit?
Base already has a lot of functional stuff (compose, partial, map &
friends) - I'm wondering if it fits there or if all the functional
stuff should be in a seperate module MochiKit.Functional - as Python
seems to be heading.
cheers,
Arnar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Bob Ippolito
2008-12-18 16:07:51 UTC
Permalink
The difference between currying and partial application is that you
can call a curried function f with 1 argument that needs N arguments
and the return value is a function f_1 that needs N-1 arguments and
when called again with 1 argument will return a function f_2 that
takes N-2 arguments, etc. until some point where N-K=0 and it returns
a value instead of another function.

It's effectively a transform that wraps a function f(a, b, c) with
something like this:
function (a) { return function (b) { return function (c) { return f(a,
b, c); } } }

Partial application explicitly takes a function with N arguments and
returns a function that takes N-K arguments but the resulting function
behaves the same as any other function in JS without that "magic".

I'm not a real big fan of currying in languages where it's not
built-in. It's easy to make a mistake by calling a function with too
few arguments and you get a harder to track down bug. It also doesn't
work well with languages that have default arguments or the equivalent
(e.g. using the arguments object) because you don't know exactly when
to stop currying.
Post by Per Cederberg
The names "curry" and "uncurry" were a bit confusing to me, so it took
me a while to understand these two functions...
http://en.wikipedia.org/wiki/Currying
To me (and probably other non-Haskell users) the names imply the same
thing as bind or partial. It's a confusing world... :-(
var test = [ [10, 1], [20, 2], [30, 3] ];
var addArray = bind("apply", operator.add, null);
assertEqual(map(addArray, test), [11, 22, 33]);
It's no beauty, so perhaps this particular variant of bind merits an
alias? Uncurrying is just the same as the built-in apply function, so
that seems unnecessary.
Cheers,
/Per
Post by Arnar Birgisson
One thing I think could be useful is to port Haskell's curry and
uncurry. This is basically a convenience method for (un)wrapping an
function curry(f) {
return function () {
// first convert arguments to a regular array
var args = Array.prototype.slice.call(arguments);
return f(args);
}
}
function uncurry(f) {
return function (args) {
return f.apply(this, args);
}
}
test = [ [10, 1],
[20, 2],
[30, 3] ];
assertEqual(map(uncurry(operator.plus), test), [11, 22, 33]);
// assume join is a function that takes a list and returns a string
// with the elements joined with some delimiter
f = curry(partial(join, _, ", "))
assert(f("Bond", "James Bond") == "Bond, James Bond")
Does anyone else think this could be useful? What module would it fit?
Base already has a lot of functional stuff (compose, partial, map &
friends) - I'm wondering if it fits there or if all the functional
stuff should be in a seperate module MochiKit.Functional - as Python
seems to be heading.
cheers,
Arnar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Arnar Birgisson
2008-12-18 16:25:31 UTC
Permalink
Hi all,
Post by Bob Ippolito
I'm not a real big fan of currying in languages where it's not
built-in. It's easy to make a mistake by calling a function with too
few arguments and you get a harder to track down bug. It also doesn't
work well with languages that have default arguments or the equivalent
(e.g. using the arguments object) because you don't know exactly when
to stop currying.
Actually, the functions I proposed (curry and uncurry, stolen form
Haskell) do not describe this kind of currying.

curry takes a function of one argument, a tuple, and returns a
modified function that instead takes N arguments (the elements of the
tuple). The reason for the name curry is that it basically performs
the translation you (Bob) mentioned in Haskell, i.e. it transforms an
N argument function to a nesting of N one-argument functions, i.e. it
"curries" the function.

uncurry takes a function of N arguments and returns a modified
function that instead takes one argument, a tuple of N elements.
Obviously the naming comes from this being the reverse of curry.

The absolute main use case is mapping functions over a list of tuples
(in js list=tuple). This uses uncurry to change a function f(a,b) to
f(t) where t is a tuble of a and b. That way you can simply map (or
filter) the function over the outer list and arguments get placed in
the correct spot.

Currying is a convenience for changing a function that takes a tuple
(i.e. a list in js) and apply it with the tuple elements as arguments
-- i.e. exactly what Function.apply does in js. I'd still include it
if uncurry is included, for the sake of symmetry.

I do realize this might be a bit too eccentric -- but it is the kind
of thing that becomes very useful to grab when you do a lot of
functional-style programming in any language.

Per provided bind("apply", operator.add, null) as equivalent to
uncurry. This is true, except that the context (this) is not
maintained.. but yes, maybe it is my weird style but I'd give an alias
to this.

Dunno.. I'm happy to keep it in my personal library of helper functions :)

cheers,
Arnar

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Per Cederberg
2008-12-18 20:32:23 UTC
Permalink
Thanks for the clarification, Bob!

Regarding the functions in questions I think other names might be in
place, to avoid misleading interpretations. What we're really doing
here is attempting to patch the poor JavaScript syntax and/or standard
library for function calls (i.e. call, apply, arguments and others).

The current MochiKit work-around for this is the excellent bind()
function (in its many incarnations). But it still has weaknesses,
since it doesn't allow us to do any of the following cool things:

1. Use the call-time 'this' object as an argument to the function (can
only be used as the object). If we had this, the "currying" mentioned
here would strictly be a version of bind().

2. Leaving gaps for call-time arguments in the list arguments set at
bind-time. Currently call-time arguments can only be appended to the
argument list.

3. Perform reordering of arguments. Typically inverse two arguments,
like in the startsWith discussion.

4. Perform random argument transformation. Using an array as the
argument list or vice versa. Or adding automatic flattening to
arguments.

The more I think about this, I tend to come to the conclusion that we
need something powerful enough to allow both the current bind() and
all of the above. Perhaps the syntax needn't be trivial, since we
could then add simplifying aliases for whatever common use-cases we
can identify.

One option, for example, would be a bind-version that would actually
map each function argument:

caller(func, self, { value: "123" }, { arg: 3 }, { arg: 1 }, { arg: -1 });

Another might be to create higher order argument-mapping functions:

var flip = function (func, self, args) { return args.reverse(); };
caller(func, self, flip);

These were just two ideas off the top of my head. But I think we
should discuss more options here before plunging ahead and adding yet
another variant of bind to MochiKit. Although they might all be very
useful. It will slowly get too confusing for the average user.

Thanks for reading this far! :-)

Cheers,

/Per
Post by Arnar Birgisson
Hi all,
Post by Bob Ippolito
I'm not a real big fan of currying in languages where it's not
built-in. It's easy to make a mistake by calling a function with too
few arguments and you get a harder to track down bug. It also doesn't
work well with languages that have default arguments or the equivalent
(e.g. using the arguments object) because you don't know exactly when
to stop currying.
Actually, the functions I proposed (curry and uncurry, stolen form
Haskell) do not describe this kind of currying.
curry takes a function of one argument, a tuple, and returns a
modified function that instead takes N arguments (the elements of the
tuple). The reason for the name curry is that it basically performs
the translation you (Bob) mentioned in Haskell, i.e. it transforms an
N argument function to a nesting of N one-argument functions, i.e. it
"curries" the function.
uncurry takes a function of N arguments and returns a modified
function that instead takes one argument, a tuple of N elements.
Obviously the naming comes from this being the reverse of curry.
The absolute main use case is mapping functions over a list of tuples
(in js list=tuple). This uses uncurry to change a function f(a,b) to
f(t) where t is a tuble of a and b. That way you can simply map (or
filter) the function over the outer list and arguments get placed in
the correct spot.
Currying is a convenience for changing a function that takes a tuple
(i.e. a list in js) and apply it with the tuple elements as arguments
-- i.e. exactly what Function.apply does in js. I'd still include it
if uncurry is included, for the sake of symmetry.
I do realize this might be a bit too eccentric -- but it is the kind
of thing that becomes very useful to grab when you do a lot of
functional-style programming in any language.
Per provided bind("apply", operator.add, null) as equivalent to
uncurry. This is true, except that the context (this) is not
maintained.. but yes, maybe it is my weird style but I'd give an alias
to this.
Dunno.. I'm happy to keep it in my personal library of helper functions :)
cheers,
Arnar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---
Per Cederberg
2008-12-18 21:06:57 UTC
Permalink
BTW. Interesting to read what others have done in this area:

http://osteele.com/sources/javascript/functional/
http://ejohn.org/blog/partial-functions-in-javascript/

Cheers,

/Per
Post by Per Cederberg
Thanks for the clarification, Bob!
Regarding the functions in questions I think other names might be in
place, to avoid misleading interpretations. What we're really doing
here is attempting to patch the poor JavaScript syntax and/or standard
library for function calls (i.e. call, apply, arguments and others).
The current MochiKit work-around for this is the excellent bind()
function (in its many incarnations). But it still has weaknesses,
1. Use the call-time 'this' object as an argument to the function (can
only be used as the object). If we had this, the "currying" mentioned
here would strictly be a version of bind().
2. Leaving gaps for call-time arguments in the list arguments set at
bind-time. Currently call-time arguments can only be appended to the
argument list.
3. Perform reordering of arguments. Typically inverse two arguments,
like in the startsWith discussion.
4. Perform random argument transformation. Using an array as the
argument list or vice versa. Or adding automatic flattening to
arguments.
The more I think about this, I tend to come to the conclusion that we
need something powerful enough to allow both the current bind() and
all of the above. Perhaps the syntax needn't be trivial, since we
could then add simplifying aliases for whatever common use-cases we
can identify.
One option, for example, would be a bind-version that would actually
caller(func, self, { value: "123" }, { arg: 3 }, { arg: 1 }, { arg: -1 });
var flip = function (func, self, args) { return args.reverse(); };
caller(func, self, flip);
These were just two ideas off the top of my head. But I think we
should discuss more options here before plunging ahead and adding yet
another variant of bind to MochiKit. Although they might all be very
useful. It will slowly get too confusing for the average user.
Thanks for reading this far! :-)
Cheers,
/Per
Post by Arnar Birgisson
Hi all,
Post by Bob Ippolito
I'm not a real big fan of currying in languages where it's not
built-in. It's easy to make a mistake by calling a function with too
few arguments and you get a harder to track down bug. It also doesn't
work well with languages that have default arguments or the equivalent
(e.g. using the arguments object) because you don't know exactly when
to stop currying.
Actually, the functions I proposed (curry and uncurry, stolen form
Haskell) do not describe this kind of currying.
curry takes a function of one argument, a tuple, and returns a
modified function that instead takes N arguments (the elements of the
tuple). The reason for the name curry is that it basically performs
the translation you (Bob) mentioned in Haskell, i.e. it transforms an
N argument function to a nesting of N one-argument functions, i.e. it
"curries" the function.
uncurry takes a function of N arguments and returns a modified
function that instead takes one argument, a tuple of N elements.
Obviously the naming comes from this being the reverse of curry.
The absolute main use case is mapping functions over a list of tuples
(in js list=tuple). This uses uncurry to change a function f(a,b) to
f(t) where t is a tuble of a and b. That way you can simply map (or
filter) the function over the outer list and arguments get placed in
the correct spot.
Currying is a convenience for changing a function that takes a tuple
(i.e. a list in js) and apply it with the tuple elements as arguments
-- i.e. exactly what Function.apply does in js. I'd still include it
if uncurry is included, for the sake of symmetry.
I do realize this might be a bit too eccentric -- but it is the kind
of thing that becomes very useful to grab when you do a lot of
functional-style programming in any language.
Per provided bind("apply", operator.add, null) as equivalent to
uncurry. This is true, except that the context (this) is not
maintained.. but yes, maybe it is my weird style but I'd give an alias
to this.
Dunno.. I'm happy to keep it in my personal library of helper functions :)
cheers,
Arnar
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "MochiKit" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to mochikit+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---

Loading...