W3C home > Mailing lists > Public > public-script-coord@w3.org > July to September 2011

Re: [WebIDL] Handling undefined in Overload Resolution Algorithm

From: Allen Wirfs-Brock <allen@wirfs-brock.com>
Date: Thu, 21 Jul 2011 17:17:58 -0700
Cc: Boris Zbarsky <bzbarsky@mit.edu>, public-script-coord@w3.org
Message-Id: <FA386ED3-D07B-4B6F-8CB8-250B98727480@wirfs-brock.com>
To: Jonas Sicking <jonas@sicking.cc>

On Jul 21, 2011, at 3:38 PM, Jonas Sicking wrote:

> On Tue, Jul 19, 2011 at 6:53 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
>> On 7/19/11 7:53 PM, Allen Wirfs-Brock wrote:
>>> 
>>> elm.querySelector(myself, undefined)  and elm.querySelector(myself) are
>>> borderline indistinguishable from the perspective of elm.querySelector if it
>>> was implemented as an ECMAScript function.  Assume that such a function is
>>> defined as:
>> 
>> Well, if you don't check arguments.length, as you point out.  Just like in
>> the C++ implementation of this, actually... ;)
> 
> Indeed. One way to look at the posed question here is: Are JS
> developers more used to code checking arguments.length, or looking for
> which arguments have the value <undefined>?
> 
> My impression is that Allen is saying that the latter is more common in JS land.

Starting  from the fact that ECMAScript does not have overloaded function definitions, a simple rule is used when the number of actual arguments is different from the number of formal parameters: extra arguments are ignored and undefined is passed as the value of missing arguments.

It is possible using the "arguments object" to determine the exact number of arguments and to access a variable number of arguments but either takes extra work.  Writing Java-style definitions where the number of arguments logically selects different functionality is possible but not necessarily good form.  It is possible to define a function foo such that foo() and foo(undefined) do different things but it would be unusual.  There are a handful of built-in ECMAScript functions,  such as the Date constructor, that do this.  I think this design for Date is a legacy of copying the Java Date constructor overloads.  It's not a pattern that we are likely to adopt for any future built-ins.

From a "feels right in JavaScript" perspective it would be best if web APIs designers stopped this sort of semantic overloading based upon argument counts and just followed the JS convention.   Unfortunately, the overloading feature of WebIDL and fimilarity with Java/C++/C# probably encourages the opposite behavior.   A good usage guideline for API designers would be: Use WebIDL overloading when you have to define how to handle type conversion alternatives in the arguments to what is logically and semantically a single function.  Don't use overloading based on the number of arguments as a way to give logically different functions the same name.

> 
> This raises another interesting question. For a function like:
> 
>  void func(optional in DOMString param2);
> 
> What should we do for code like:
> 
> o.func(undefined);
> 
> Should that behave like
> 
> o.func();
> 
> or
> 
> o.func("undefined");
> 
> I believe the spec currently says the latter, but Allen's argument
> would indicate that the former is what developers would expect?

In one sense, this question is about what is the difference between describing to a JS programmer a function signature as:
   void func(optional in DOMString param1);
rather than as
   void func(in DOMString param1);

as in JS you can invoke it as
   o.func()
in either case.

If they mean the same thing, then why do we even need the optional modifier?  Such a function could be implemented in JS to do any of the various alternatives but I think a reasonable convention that probably produces least astonishment would be:
      void func(in DOMString param1);  -- One required string argument, so it always converts param1 to a string; hence func() is the same as func("undefined")
and
      void func(optional in DOMString param1);  -- One optional string argument, so it  only converts param1 to a string it it is not undefined;  hence func() is the same as func(undefined)

null would have to be explicitly passed in either case so normal JS conversion logic would convert it to "null".  A JS implementor of such a function would have to add extra code to not convert null to "null" and they would probably only bother to do that if the function was actually specified to do something different for null.

> 
> This is something that has actually come up. [1] shows one site
> breaking over expecting the former behavior when Firefox implemented
> the latter.
> 
> [1] https://bugzilla.mozilla.org/show_bug.cgi?id=605296
> 
> / Jonas
> 
Received on Friday, 22 July 2011 00:18:33 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 8 May 2013 19:30:04 UTC