- From: Cameron McCormack <cam@mcc.id.au>
- Date: Wed, 14 Dec 2011 15:00:25 +1100
- To: Anne van Kesteren <annevk@opera.com>
- CC: public-script-coord@w3.org
On 18/09/11 7:57 AM, Anne van Kesteren wrote: > For the DOM we have this idea of having a method that can conveniently > create an element, set its attributes, event handlers, and child nodes. > However, to keep the method convenient some of those need to become > optional and therefore it requires some kind of overloading, which is > where things become problematic. > > Maybe there is a better design, but so far we have something like this: > > create(name) > create(name, attributes) > create(name, children) > create(name, attributes, children) > create(name, attributes, eventhandlers, children) > > name is a string. > > attributes is an object. > > eventhandlers is an object. > > children is either a Node or string, or an array of Nodes and strings. > > Examples: > > create('h1', 'Welcome!') > create('button', {name: 'command', value: 'search'}, {onclick: teehee}, > 'Search') > create('p', {title: 'hi'}, [node, node2]) > > The problem is however that arrays and objects are not really > distinguishable unless you do "evil things". > > Anyone with ideas? First, there's no way in Web IDL currently to support the attributes argument you have above, unless you write Node create(DOMString name, object attributes) and then in prose dig into the JS properties of the object passed in. This may or not be in good taste. If we want to support it, we should introduce a type that is like an open ended dictionary, e.g. Node create(DOMString name, dictionary<DOMString> attributes); Let me know if you are still pursuing an API like the above so I know whether to consider something like dictionary<DOMString>. But to your main question, you are correct that you can't write: void f(Node x); void f(DOMString x); void f(sequence<Node or DOMString> xs); (to use your proposed union type syntax) since interface types (like Node) aren't distinguishable from sequence types. I think one of the advantages of the way sequence<T> is treated currently is that it can take not only a JS Array object, but any object at all, since it will just look up a "length" property and then any array index properties. This is handy because array-like non-Array objects like NodeList can be passed to the function without having to allow it explicitly in the IDL. So far in the overload resolution algorithm I have avoided making any two object-like types distinguishable unless it is solely on the basis of which interface they implement. Now you could just say "if it has a length property, choose the sequence one", but then if you wrote void g(NodeList x); void g(sequence<Node> xs); we have another one of those situations where a value can plausibly be considered to match more than one overload. Remember that we have this problem already with interfaces (technically, if not in practice): void h(InterfaceA x); void h(InterfaceB x); What happens when an object that implements both interfaces is passed in? We currently have in the spec that we just choose the first one. We could do the same for NodeList vs sequence<Node>. We might have to resolve the "overload resolution consistency" thread to see whether it makes sense to do this.
Received on Wednesday, 14 December 2011 04:00:58 UTC