Re: Reconciling handling of optional arguments and handling of default values across ES and webidl

On Wed, May 8, 2013 at 11:18 AM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
> This keeps coming up, so here comes a proposal....  I believe what I'm
> proposing does not represent the status quo for either ES6 or WebIDL, but it
> seems like the sanest available behavior to me, and I'd like to see what the
> objections are to it.  I am aware that there has been a good bit of
> discussion about this in ES6, and I've read all of it that I could find, for
> what it's worth.  And I think that people are undecided about how exactly
> "optional" arguments and "default values" should work, which is leading to
> some wackiness.
>
> WebIDL behavior:
>
> 1)  Allow any argument to be marked as optional in WebIDL, even if followed
> by non-optional ones.
>
> 2)  Allow any argument that is optional to have a default value provided in
> WebIDL, even if followed or preceded by optional arguments without default
> values.
>
> 3)  Treat undefined passed for an optional argument as "not passed".  If
> there is a default value, the default value takes effect.

All of this sounds great.

> ES behavior:
>
> 1)  Allow specifying a default value for any function argument, even if
> followed or preceded by arguments without default values, with the default
> taking effect if undefined is passed.

Sounds good.

> 2)  Have arguments.length not include trailing undefined values.

This I'm not so sure about. While I think that treating undefined as
"use default behavior", aka "not passed" is likely the right behavior
in almost every case, it seems scary to completely disable the ability
for the callee to tell if undefined was explicitly passed or not. I.e.
this removes the ability for a function to accept any value, while
also having a different behavior for "nothing was passed".

Being able to inspect arguments.length has always seemed like a nice
escape valve to satisfy the odd use case where people wanted to make
the distinction.

I take it that you are also proposing that

3) rest parameters wouldn't pick up any trailing undefined values.

I.e.

function x(...a) {
  console.log(a.length);
}
x(undefined)

would show 0?

I think this one is slightly trickier since I do agree that treating
undefined as "not passed" is a good default behavior. But when you
have rest parameters it feels like you are more likely to be passing
effectively an array rather than different parameters with different
semantics.

I don't have a strong opinion either way though.

/ Jonas

> I believe this will completely align the observable behavior of the two and
> the capabilities available to both JS functions and C++ implementations of
> WebIDL functions in terms introspecting the arguments.  The mental model is
> "undefined should act just like not passed".
>
> In trailing position that means you can in fact omit the arguments, or pass
> undefined, and you get the same arguments.length either way, and the same
> default-value handling.
>
> In non-trailing position you have to explicitly pass undefined to get the
> default, unless we grow named-argument passing a la python.  If we do, it
> would still be compatible with the above proposal, I believe, though at that
> point arguments.length and indexing into arguments might need a bit more
> discussion.  ;)
>
> Thoughts?
>
> -Boris
>

Received on Wednesday, 8 May 2013 22:26:44 UTC