Enforcing arity?

# Axel Rauschmayer (12 years ago)

What is the simplest way of enforcing an arity in ES6? Doesn’t it involve arguments?

function add(x, y) { if (arguments.length !== 2) throw ... }

To avoid argument, one could:

  • ensure a maximum arity by adding a ...rest parameter and checking that its length is 0.
  • ensure a minimum arity, by giving y a default value and checking for it.

Would fail-fast destructuring work?

function add(...args) { let [x,y] = args; }

# Herby Vojčík (12 years ago)

Axel Rauschmayer wrote:

What is the simplest way of enforcing an arity in ES6? Doesn’t it involve arguments?

function add(x, y) { if (arguments.length !== 2) throw ... }

To avoid argument, one could:

  • ensure a maximum arity by adding a ...rest parameter and checking that its length is 0.
  • ensure a minimum arity, by giving y a default value and checking for it.

Would fail-fast destructuring work?

function add(...args) { let [x,y] = args; }

And it this would be possible, it could be in the signature:

function add(...[x,y,opt?]) { }

# Rick Waldron (12 years ago)

On Sunday, January 6, 2013, Axel Rauschmayer wrote:

What is the simplest way of enforcing an arity in ES6? Doesn’t it involve arguments?

function add(x, y) { if (arguments.length !== 2) throw ... }

To avoid argument, one could:

  • ensure a maximum arity by adding a ...rest parameter and checking that its length is 0.

I can't find the thread, but a similar question was asked sometime in the last 6 months (I think??) and this was the answer that was ultimately agreed on as the best way to check arity length.

  • ensure a minimum arity, by giving y a default value and checking for it.

Explicit undefined arguments, intentional or not, would trigger the default value.

# Jason Orendorff (12 years ago)

On Sun, Jan 6, 2013 at 6:31 PM, Axel Rauschmayer <axel at rauschma.de> wrote:

What is the simplest way of enforcing an arity in ES6? Doesn’t it involve arguments?

Hmm. Can you do this?

function f(x, y, ...[]) {}
# Brandon Benvie (12 years ago)

The outcome of that discussion was here: esdiscuss/2012-December/027386

I used that solution for a short while, but ultimately I resorted to trickery to implement it for the ES6 stdlib using an internal $$ArgumentCount function. The reason is that it's actually observable via the debugging API I provide what the structure of the params for a particular function are (this is visible in the debugger), and presenting an param as rest for the sole purpose of avoiding the arguments object didn't seem worth it. Still though, it remains possible (if not particularly graceful) to do this using ...rest without resorting to either arguments or internal hacks.

# Brendan Eich (12 years ago)

Jason Orendorff wrote:

On Sun, Jan 6, 2013 at 6:31 PM, Axel Rauschmayer <axel at rauschma.de <mailto:axel at rauschma.de>> wrote:

What is the simplest way of enforcing an arity in ES6? Doesn’t it
involve arguments?

Hmm. Can you do this?

function f(x, y, ...[]) {}

The question is, with refutable-by-default, does the empty array pattern fail on any non-empty arraylike match target? If yes, then we need a way to match prefixes of arraylikes (including empty prefixes!):

let [] = must_be_empty(); let [...many] = however_many(); let [first?, second?] = two();

I buy it!

# Axel Rauschmayer (12 years ago)

I’m torn: On one hand, I love the cleverness of it and it is certainly a good solution (and one that doesn’t necessitate introducing new language features).

On the other hand, I’m wondering if it wouldn’t be cleaner to have a per-function flag that tells JavaScript to enforce the specified arity (which can be done quite precisely, thanks to ES6’s advanced parameter handling). One possibility for setting such a flag are Python-style decorators: www.python.org/dev/peps/pep-0318

Axel

# Axel Rauschmayer (12 years ago)

What is the recommended way of enforcing arity under ECMAScript 6 (while avoiding arguments.length)?

Two ideas:

  1. Parameter default value is a function call that throws an exception. Not sure if that works. function foo(required = throwAnException(), optional) { ... }

  2. Introduce a postfix ! matching operator, the inverse of postfix ?: function foo(required!, optional) { ... }

# Allen Wirfs-Brock (12 years ago)

If you need to do arity analysis of parameter but also what to apply default values, destructuring, etc I would do the following:

Instead of function ([a,b], c,d=5, ...rest) {...} do function (...args) { if (args.length <3) throw Error("too few arguments"); let [[a,b], c,d=5, ...rest] = args; //probably need some ?'s in there, but I haven't internalized the details of the new pattern matching yet. }

# Axel Rauschmayer (12 years ago)

On Mar 17, 2013, at 1:17 , Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

If you need to do arity analysis of parameter but also what to apply default values, destructuring, etc I would do the following:

Instead of function ([a,b], c,d=5, ...rest) {...} do function (...args) { if (args.length <3) throw Error("too few arguments"); // (*) let [[a,b], c,d=5, ...rest] = args; //probably need some ?'s in there, but I haven't internalized the details of the new pattern matching yet. }

Nice, I forgot about rest parameters. You’d still get an exception from matching if you omitted line (*), right? Shame that we can’t have the destructuring semantics for parameters.

# Kevin Gadd (12 years ago)

Would using (...args) incur a performance penalty and impair optimization since the argument list has to be an array now? Or is that still better than using 'arguments.length'? Enforcing arity is a common enough (and important, IMO) pattern that I'd be wary of doing it using a pattern that is going to slow everything down. Something that makes every call create garbage seems like a likely candidate to do that.

# Allen Wirfs-Brock (12 years ago)

It's certainly plausible that an implementation could do the analysis to recognize this pattern and implement it so there isn't an extra allocation or any extra copying.

It it became an common perf. bottleneck you might expect the better implementation to do so. If it isn't a common perf. issue, then it really doesn't matter.