Curried functions in JavaScript (how to employ genericly, and invisibly)?

Discussion in 'Javascript' started by svend, Jul 22, 2003.

  1. svend

    svend Guest

    Hey there,

    I was thinking about some curried functions in JavaScript, and I made
    this:

    <script>
    function add(a, b, c) {
    if (arguments.length == 1) {
    return function (d,e) {return a + d + e}
    }
    if (arguments.length == 2) {
    return function (d) {return a + b + d}
    }
    return a + b + c;
    }

    t = add(1,2);
    alert(t(3));

    alert(add(1,2,3));
    </script>

    Which works, but it's ugly, to say the least. So I was wondering, if
    there's a way, to create this, in a more generic way? I'm aware, that
    it probably wont be SML like curried, which is totally transparent,
    but is there anyway at all?

    In a way, so that it works, as close to SML as possible, though I'm
    willing to accept, some code will be needed?

    Regards,
    Svend
     
    svend, Jul 22, 2003
    #1
    1. Advertising

  2. > I was thinking about some curried functions in JavaScript, and I made
    > this:
    >
    > <script>
    > function add(a, b, c) {
    > if (arguments.length == 1) {
    > return function (d,e) {return a + d + e}
    > }
    > if (arguments.length == 2) {
    > return function (d) {return a + b + d}
    > }
    > return a + b + c;
    > }
    >
    > t = add(1,2);
    > alert(t(3));
    >
    > alert(add(1,2,3));
    > </script>
    >
    > Which works, but it's ugly, to say the least. So I was wondering, if
    > there's a way, to create this, in a more generic way? I'm aware, that
    > it probably wont be SML like curried, which is totally transparent,
    > but is there anyway at all?
    >
    > In a way, so that it works, as close to SML as possible, though I'm
    > willing to accept, some code will be needed?


    You could write an array method sum() that would take an array and return its
    sum. Then you can capture arguments as an array and apply sum to it to get a
    value. That might be a little bit prettier.

    http://www.crockford.com/javascript/little.html
     
    Douglas Crockford, Jul 22, 2003
    #2
    1. Advertising

  3. svend

    Dom Leonard Guest

    Re: Curried functions in JavaScript (how to employ genericly, andinvisibly)?

    Svend Tofte wrote:
    <snip> I ...
    was actually
    > thinking of something even more generic. Something, like an array, and
    > could return a new function, which would call the original function..
    >
    > ala:
    >
    > function x() {
    > return new function() {x(argumentsArray)}
    > }
    > Returning a function, that would call "x", with the arguments, passed
    > to the first call of "x", in the right order, and then apply the new
    > arguments, afterwards.
    >


    Function .length property and .apply method might be useful, ala

    function makeCurry(func,oldArgs)
    {
    var length=func.length;
    var oldLength = oldArgs ? oldArgs.length : 0;
    function curry()
    {
    var i;
    var myLength=arguments.length;
    var newArgs;
    if((oldLength==0) && (myLength >= length))
    return func.apply(this,arguments);
    if(myLength==0)
    return curry; // no change
    newArgs = new Array();
    for(i=0; i < oldLength; ++i)
    newArgs.push(oldArgs);
    for(i=0; i < myLength; ++i)
    newArgs.push(arguments);
    return (newArgs.length >= length) ?
    func.apply(this,newArgs) :
    makeCurry(func,newArgs) ;
    };
    return length ? curry : func;
    }

    // as tested in Mozilla

    function add(a,b,c)
    {
    return a+b+c;
    }
    var cAdd=makeCurry(add);
    cAdd(2,4,8); //= 14
    cAdd(2)(4)(8) //= 14
    cAdd(2,4)(8) //= 14
    cAdd(2)(4,8) //= 14
    cAdd(2)()(4)()(8) //= 14

    =======

    When working up the code I ran into problems with the arguments array
    not being an instance of javascript's Array constructor (I think), so
    simply almalgamated old and new arguments in a loop.

    HTH,
    Dom
     
    Dom Leonard, Jul 24, 2003
    #3
  4. > When working up the code I ran into problems with the arguments array
    > not being an instance of javascript's Array constructor (I think), so
    > simply almalgamated old and new arguments in a loop.


    That is really annoying, isn't it? A coding mistake in Netscape was reverse
    engineered and copied into JScript, and then written into the standard.

    This will produce a real array from arguments :

    Array.prototype.slice.apply(arguments)

    You can also give slice additional parameters for removing some initial
    parameters from the array at the same time.

    http://www.crockford.com/
     
    Douglas Crockford, Jul 24, 2003
    #4
  5. svend

    Fox Guest

    Re: Curried functions in JavaScript (how to employ genericly, andinvisibly)?

    If I understand the material correctly:

    function
    Curry()
    {
    this.accumulator = 0;

    function curry(arry)
    {
    var f = arry[0];
    var count = 1;
    while(count < arry.length)
    {
    f(arry[count++]);
    }
    }

    if(arguments.length > 1)
    {
    curry(arguments);
    }

    return this.accumulator;
    }

    // test:

    function
    add(n)
    {
    this.accumulator += n;
    }

    function
    mult(n)
    {
    if(this.accumulator == 0)
    this.accumulator = 1;
    this.accumulator *= n;
    }



    alert(Curry(add, 1, 2, 3, 4, 5));
    alert(Curry(mult, 1, 2, 3, 4, 5));

    or you can just inline the functions:

    Curry(function(i){ this.accumulator += i; }, 1,2,3,4,5);
    etc...


    ************************************************




    svend wrote:
    >
    > Hey there,
    >
    > I was thinking about some curried functions in JavaScript, and I made
    > this:
    >
    > <script>
    > function add(a, b, c) {
    > if (arguments.length == 1) {
    > return function (d,e) {return a + d + e}
    > }
    > if (arguments.length == 2) {
    > return function (d) {return a + b + d}
    > }
    > return a + b + c;
    > }
    >
    > t = add(1,2);
    > alert(t(3));
    >
    > alert(add(1,2,3));
    > </script>
    >
    > Which works, but it's ugly, to say the least. So I was wondering, if
    > there's a way, to create this, in a more generic way? I'm aware, that
    > it probably wont be SML like curried, which is totally transparent,
    > but is there anyway at all?
    >
    > In a way, so that it works, as close to SML as possible, though I'm
    > willing to accept, some code will be needed?
    >
    > Regards,
    > Svend
     
    Fox, Jul 24, 2003
    #5
  6. (svend) writes:

    > In a way, so that it works, as close to SML as possible, though I'm
    > willing to accept, some code will be needed?



    How about this currying function:
    ---
    function curry(f,n) { // n is number of arguments for f
    return function() {
    var cnt = n;
    var accu = [];
    var self=this;
    function accumulate(args) {
    for(var i=0;i<args.length;i++) {
    accu[accu.length]=args;
    cnt--;
    }
    if (cnt<=0) {
    return (f.apply(self,accu));
    } else {
    return function(){return accumulate(arguments);};
    }
    }
    return accumulate(arguments);
    }
    }
    ---
    And even
    Function.prototype.curry = function(n){return curry(this,n);};

    Then you can write

    function f(a,b,c){ return a+b+c; };

    and

    var g= f.curry(3);
    g(1,2,3) + g(1)(2)(3) + g(1,2)(3)

    /L 'the wonders of untyped languages!'
    --
    Lasse Reichstein Nielsen -
    Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Jul 24, 2003
    #6
  7. svend

    Dom Leonard Guest

    Re: Curried functions in JavaScript (how to employ genericly, andinvisibly)?

    Douglas Crockford wrote:

    > This will produce a real array from arguments :
    >
    > Array.prototype.slice.apply(arguments)
    >

    Thanks for the thought - whilst not using it exactly, put me on a
    suitable track. FWIW, the makeCurry function reduced to

    function makeCurry(func,oldArgs)
    { function curry()
    { var newArgs = arguments;
    if(newArgs.length ==0)
    return curry; // no change
    if(oldArgs)
    { newArgs=new Array();
    newArgs.push.apply(newArgs,oldArgs);
    newArgs.push.apply(newArgs,arguments);
    }
    return (newArgs.length >= func.length) ?
    func.apply(this,newArgs) :
    makeCurry(func,newArgs);
    }
    return func.length ? curry : func;
    }

    Cheers,
    Dom
     
    Dom Leonard, Jul 25, 2003
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?ISO-8859-1?Q?Holger_T=FCrk?=

    Curried functions

    =?ISO-8859-1?Q?Holger_T=FCrk?=, Jun 4, 2004, in forum: Python
    Replies:
    0
    Views:
    278
    =?ISO-8859-1?Q?Holger_T=FCrk?=
    Jun 4, 2004
  2. Scott Lamb

    Curried class methods?

    Scott Lamb, Aug 17, 2006, in forum: Python
    Replies:
    3
    Views:
    374
    Scott Lamb
    Aug 17, 2006
  3. Replies:
    16
    Views:
    931
    Herbert Blenner
    Nov 28, 2007
  4. Blinky the Shark

    Re: Nest table in table invisibly

    Blinky the Shark, Nov 27, 2007, in forum: HTML
    Replies:
    2
    Views:
    469
    Jonathan N. Little
    Nov 27, 2007
  5. mike
    Replies:
    3
    Views:
    190
Loading...

Share This Page