Understanding Generic Functions

John Resig jresig at mozilla.com
Wed Nov 14 17:26:37 PST 2007


Hey All -

So I've been trying to understand generic functions (and their presumed use for Multimethods). Reading through the white paper and the wiki I can surmise the following (and since the RI doesn't include them yet, these are just assumptions):

Generic functions are used like this:

generic function a(b);
generic function a(b:int){}
generic function a(b:string){}

Generics offer a point upon which future functions can be bound, like for operator overloading:

class Foo!{}

generic intrinsic function +(a:string, b:Foo){}
generic intrinsic function +(a:Foo, b:string){}
generic intrinsic function +(a:Foo, b:Foo){}

So that's all well-and-good. Now, where I making an assumption is that it's not possible to do the following:

generic function a(b);
generic function a(b:int){}
generic function a(b:string){}

generic function a(b,c);
generic function a(b:string, c:int){}

also, it's not clear if you can use generics for constructors - so I'm assuming that that's also not possible:

class Foo {
  generic function Foo(b);
  generic function Foo(b:int){}
  generic function Foo(b:string){}
}

Ok - with all of that assumed, I am seriously struggling to think of a real-world use case for generics beyond the compelling operator overloading example.

Assuming that I wanted to continue to try to do method overloading, it sounds like the de-facto solution is to just use the rest arguments to figure out what I want. This is not an acceptable solution. I lose virtually all of the benefits that I had of doing type annotations in the first place if I can't actually use them on "overloaded" functions.

For example, I've been pouring through my JavaScript library (jQuery) looking for ways in which ES4 could be of benefit. I immediately looked to using (what I thought was) method overloading to ease some of the severe complexity of the library. We do overloading on virtually every single method: Thus, if there was no form of method overloading included in ES4, then jQuery would receive significantly less, tangible, benefit from these updates.

To give a couple, crude, examples:

function attr(name : string) : string {
  // get attribute value
}

function attr(name : string, value : (string,int)) : jQuery {
  // set an attribute value, return a jQuery object
}

function removeEvent() : jQuery {
  // Remove all events
  for each ( var type in types )
    removeEvent( type );
}

function removeEvent(type : string) : jQuery {
  // Remove all events of a specific type
  for each ( var fn in events[type] )
    removeEvent( type, fn );
}

function removeEvent(type : string, fn: Callable) : jQuery {
  // Remove the event handler bound to a type
}

Additionally, I've been working on building a DOM implementation to sit on top of the ES4 RI, but have hit some walls, especially with constructors. Thankfully, private/protected/etc. constructors will be implemented at some point (I'm looking forward to it) but I was kind of expecting the ability to do multiple constructors - and even the ability to mix private/protected/public constructors, for example:

class Foo {
  private function Foo(){
    // Do initialization stuff
  }
  function Foo(name : string) {
    this();
    this.name = name;
  }
}

I'm simply most concerned about getting a useful version of method overloading and constructor overloading. I'd love to find out that I could use generics to achieve this, but I just don't have a way of determining that right now.

--John



More information about the Es4-discuss mailing list