undefined being treated as a missing optional argument

Oliver Hunt oliver at apple.com
Fri Apr 13 12:05:40 PDT 2012


On Apr 13, 2012, at 11:48 AM, David Herman <dherman at mozilla.com> wrote:

> On Apr 13, 2012, at 11:35 AM, Oliver Hunt wrote:
> 
>> What happens if i have:
>> 
>> function foo(a=1, b=2) { log(a, b, arguments.length); }
>> 
>> foo();
> 
> 1, 2, 2
> 
>> foo(undefined);
> 
> 1, 2, 1

Uh what? I pass no arguments and arguments.length is 2, and i pass one argument and arguments.length is 1?

Sorry, that behaviour makes no sense at all.

> 
>> foo(3);
> 
> 3, 2, 1
> 
>> foo(undefined, undefined);
> 
> 1, 2, 2

So i've passed 2 arguments, but they both get replaced?

> 
>> foo(undefined, 3);
> 
> 1, 3, 2

So if you have default values we have to emit code to check for undefined in each case?

is foo(a=5, b) valid?  The above examples imply that it should be.


> 
>> foo(3, undefined);
> 
> 3, 2, 2
> 
>> Default values are for when arguments are not passed,
> 
> Stated without evidence!

C++, python, ...


> 
>> it does not make logical sense to say that they're the value given just because someone has passed undefined.
> 
> It makes perfect sense. But hey, I had the same reaction as you at first, so I sympathize. Default values conceptually represent "no value provided," and the natural way to think of this from a language designer or implementer's perspective is to think about whether the syntax of the call included an argument at the particular position. But this is not the *programmer's* perspective. From the programmer's perspective, it's "do I have a value to provide for this argument?" And in reality, the answer to that question is often a *dynamic* one, not a static one. You often have to make the decision at runtime whether to provide a value for a given argument. When you do, the semantics based on arguments.length has terrible consequences: you either have to write a combinatorial explosion of separate calls (code bloat -- unacceptable), or you just end up reimplementing the default logic by conditionally producing the default value (abstraction violation -- unacceptable).
> 
> So after thinking more about it, I came to the conclusion that:
> 
> - default values are for when no value *of the expected input type* was provided
> - undefined is almost universally used in JS as a sentinel value for "I have no value of the expected input type," because it's not statically typed so it's not possible to express option types
> - whenever you need to make conditional decisions about whether you have a value for various arguments, the arguments.length semantics has unacceptable engineering consequences
> - in the rare cases where you want to treat undefined as an acceptable value of the expected input type, just don't use default values

This makes it impossible for me to distinguish between passing undefined as an argument and not passing an argument.  If i've written:

foo(undefined)

There's a very clear expectation that i have selected undefined as the value i want to be passed.  Yet you're saying this should be interpreted as foo() (only with a shorter arguments.length).

--Oliver

> 
> Dave
> 



More information about the es-discuss mailing list