Simon Kuang
Simon Kuang

Reputation: 3940

Chained array creator

Just for fun, I'm looking for a way to create a function, array, with the following behavior:

array()       // []
array(2)      // ugly function thing
array(2)()    // [2]
array(2)(3)() // [2,3] etc

The closest I can come is

function array(x) {
    if (x == null)
        return []
    return function() {
        // same as above?!
        // I don't want some inelegant solution involving a lot of additional parameters
    }
}

Is there a way to do this in ECMA5? If not, prove that the syntax can't accomodate such a function.

Upvotes: 0

Views: 96

Answers (2)

StackSlave
StackSlave

Reputation: 10627

I think this should do exactly what you are looking for. The self-executing function scopes off r and rr, which are basically static variables using this implementation. Of course, you need to reset r after assigning it to rr, so you can return the Array when ra has an undefined argument, which then stops the recursive behavior.

var array = (function(){
  var r = [], rr;
  function ra(a){
    if(a === undefined){
      rr = r; r = []
      return rr;
    }
    else{
      r.push(a);
      return ra;
    }
  }
  return ra;
})();
console.log(array()); console.log(array(5)()); console.log(array());
console.log(array(7)(2)());

Upvotes: -1

Bergi
Bergi

Reputation: 664484

Yes, "same as above". This is solved by a "recursive"1 call:

function makeArrayAppender(arr) {
    return function array() {
        var args = Array.prototype.slice.call(arguments);
        if (!args.length)
            return arr;
        else
            return makeArrayAppender(arr.concat(args));
    };
}
var array = makeArrayAppender([]);

1: As the function is called from the returned "thunk" function, not from the call itself, it's not really recursive. It's more like a tail-call-optimised function, being invoked manually in-a-row without filling the stack

Upvotes: 2

Related Questions