Patterns in parameter declarations: irrefutable?

# Axel Rauschmayer (13 years ago)

Are patterns in parameter declarations irrefutable? In other words, given:

function foo({ opt1 }) { return opt1 }

What happens if we call foo()? 1. An exception is thrown 2. undefined is returned I’d expect (2). If opt1 had a default value, I’d expect that value to be returned.

What happens if we call foo({})? 1. An exception is thrown 2. undefined is returned

I’m asking, because I’ve seen the pattern

function foo({ opt1 = 3 } = {}) { return opt1 }

If explicitly marking something as irrefutable is necessary, I’d prefer:

function foo({ opt1 = 3 }?) { return opt1 }

It’s a bit of a shame that destructuring and parameter declarations diverge, but I guess it can’t be helped.

Axel

# Brendan Eich (13 years ago)

The proposal we accepted, written by Andreas at harmony:refutable_matching, seems clear. Patterns are refutable without an extra ? annotation. Andreas is using prefix-?, note well.

# Axel Rauschmayer (13 years ago)

Thanks, didn’t know that applied to parameters, too. Then the following two functions are equivalent(?)

function (arg0, arg1, arg2) {
    // ...
}
function (...args) {
    let [arg0', arg1', arg2'] = args;
    // ...
}

With the following rules for translating argi -> argi':

  • paramName -> ?paramName
  • pattern -> pattern (rest parameters, parameter default values, curly braces, square brackets)
# Andreas Rossberg (12 years ago)

On 20 March 2013 23:49, Axel Rauschmayer <axel at rauschma.de> wrote:

Thanks, didn’t know that applied to parameters, too. Then the following two functions are equivalent(?)

function (arg0, arg1, arg2) {
    // ...
}
function (...args) {
    let [arg0', arg1', arg2'] = args;
    // ...
}

With the following rules for translating argi -> argi':

  • paramName -> ?paramName
  • pattern -> pattern (rest parameters, parameter default values, curly braces, square brackets)

Not quite. In the latter form, default expressions could see all local declarations from the function body, which we decided a couple of meetings ago should not be the case for the former. More pedantically, 'paramName' should probably include parenthesized identifiers, and 'pattern' sloppy patterns ?pattern. (The latter also introduces a new variable 'args' into the scope and produces a different length property for the function, but let's ignore that.)

The more accurate desugaring probably is

function f(pat1, ..., patN, ...patR) { body }

into

function f() { let pat1 = arguments[0] ... let patN = arguments[N-1] let [?, ..., ?, ...patR] = arguments return (function(){ body })(...arguments) }

(still ignoring the length property, and taking the liberty of using * as a wildcard pattern to avoid inventing variable names).