Mutable `length` for functions?

# Nathan Wall (13 years ago)

Would it be possible to make / what are the thoughts on making length mutable on functions?

Writing to length could be a useful functionality for library code. For instance, implementing something like bind correctly requires the arity of the bound function to be the same as the original function minus the number of preloaded arguments.

Simplified example:

var slice = Function.prototype.call.bind(Array.prototype.slice);
function bind(f, thisArg, ...args) {
  function bound() {
    return f.apply(thisArg, args.concat(slice(arguments)));
  }
  var L = f.length - args.length;
  bound.length = L > 0 ? L : 0;
  return bound;
}

Of course, bind is already on Function.prototype, so an ES6 library has no need to implement it. I'm only using bind as an example to establish?precedent?that writable length could be useful in implementing function wrappers. ?Consider as a more necessary example implementing an uncurryThis function.

var uncurryThis = Function.prototype.bind.bind(Function.prototype.call);
function foo(a, b, c) { /* ... */ }
var uFoo = uncurryThis(foo);
console.log(
  foo.length, // => 3
  uFoo.length // => 1
);

This is problematic because we lose information about the arity of the uFoo function which actually takes 4 arguments now: A this argument, a, b, and c. ?A simple solution would be to write an uncurryThis which corrects the arity:

var bind = Function.prototype.call.bind(Function.prototype.bind),
    callMethod = Function.prototype.call;
function uncurryThis(fn) {
  var F = bind(callMethod, fn);
  // Correct arity.
  F.length = fn.length + 1;
  return F;
}
function foo(a, b, c) { /* ... */ }
var uFoo = uncurryThis(foo);
console.log(
  foo.length, // => 3
  uFoo.length // => 4
);

Currently I have resorted to an eval based solution for creating wrapper functions which are defined with the correct number of arguments when a certain arity is desired. Obviously this is not ideal. Writable length would help a lot.

# Claude Pache (13 years ago)

An alternative to a writable length property, is to make it configurable and nonwritable. It would prevent the issue of accidental assignments to the length property that used be ignored in non-strict mode (they'll still be ignored), but it would allow to modify its value using Object.defineProperty.

-Claude

# Brendan Eich (13 years ago)

Claude Pache wrote:

An alternative to a writable 'length' property, is to make it configurable and nonwritable. It would prevent the issue of accidental assignments to the 'length' property that used be ignored in non-strict mode (they'll still be ignored), but it would allow to modify its value using Object.defineProperty.

That's not half-bad.

I used to tell Allen I saw no purpose in non-writable but configurable, but against the backdrop of JS history, I see it.

Mark, does this cause SES problems?

# Mark S. Miller (13 years ago)

[+google-caja-discuss]

I don't see any problems for SES. cc'ing google-caja-discuss in case someone there spots something I missed. Anyone?

Assuming there are no problems, I like this for all the reasons stated.

# Allen Wirfs-Brock (13 years ago)

On Feb 26, 2013, at 11:22 AM, Brendan Eich wrote:

Claude Pache wrote:

An alternative to a writable 'length' property, is to make it configurable and nonwritable. It would prevent the issue of accidental assignments to the 'length' property that used be ignored in non-strict mode (they'll still be ignored), but it would allow to modify its value using Object.defineProperty.

That's not half-bad.

I used to tell Allen I saw no purpose in non-writable but configurable, but against the backdrop of JS history, I see it.

Like I've said before, I play the long game. Eventually you usually come around :-)

I think non-writable/configurable properties a very nice balance point between those developer who value the mutable/hackable/patchable nature of JS and those who desire to minimize JS foot-guns. If you know what you are doing you can modify them using Object.defineProperty but a naive assignment will fail (noisily in strict mode).

If we start to appreciate this distinction, there are probably a few other ES6 properties that this would make sense for. The "constructor" property on prototype objects created by class definitions is one that immediately comes to mind.

# Brendan Eich (13 years ago)

Allen Wirfs-Brock wrote:

Like I've said before, I play the long game. Eventually you usually come around:-)

Except when you're off target :-P.

But good long-game on this one -- well played!