callable objects ?

David Bruant bruant.d at gmail.com
Wed Apr 4 00:56:23 PDT 2012


Le 04/04/2012 02:41, Irakli Gozalishvili a écrit :
>
> On Tuesday, 2012-04-03 at 14:07 , David Bruant wrote:
>
>> Le 03/04/2012 22:00, Irakli Gozalishvili a écrit :
>>> Here is more or less what I have in mind: 
>>> https://gist.github.com/2295048
>>>
>>> // class
>>> var Point = {
>>> (x, y) {
>>> this.getX = { () { return x; } }
>>> this.getY = { () { return x; } }
>>> }
>>> toString() {
>>> return '<' + this.getX() + ',' + this.getY() + '>';
>>> }
>>> }
>> Interesting new function syntax.
>> The prototype and function body could even be declared together. What 
>> about 'length'?
>>
>>> Also such callable objects provide shorter alternative to current 
>>> function syntax:
>>> // shorter than function
>>> numbers.
>>> filter({ (x) { return x % 2 } }).
>>> // maybe single expression can be even shorter like arrow functions ?
>>> map({ (x) x * x }).
>>> forEach({ (x) { this.add(x) } }, that);
>> +1
>>
>>> Also this would allow interesting APIs similar to those found in 
>>> clojure:
>>>
>>> // maps / sets similar like in clojure ?
>>> var map = WeakMap(), key = {}, value = {};
>>> map.set(key, value);
>>> map(key) // => value
>> So far so good.
>>
>>> key(map) // => value
>> This cannot work for backward-compat reasons. In ES1-5, "key = {}" 
>> creates a regular (non-callable) object.
>>
>
>
> Well I did not suggested it should be backwards compatible, also nor 
> classes nor shorter object syntax is backwards compatible.
>
They are to the extent that they throw an error for being invalid syntax 
in previous version. This is the case for your proposal and that's a 
good thing since that's the back door to introducing new features.
However, proposals should be backward compatible in semantics.

In your case:

     var map = WeakMap(), key = {}, value = {};
     map.set(key, value);
     map(key) // => value
     key(map) // => value

since key is callable, you have (typeof key === 'function') while ES5 
requires (typeof key === 'object') for objects that are constructed with 
'{}'. There is code out there that relies on typeof for argument 
shifting: 'if the first argument is a function, use that as callback, 
otherwise, use the second argument (first argument being an option 
non-callable object)'. There is this pattern all over the place in the 
mongodb node client as in 
https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L85
In other cases, to pass a handler, some API check if the argument if an 
object and in that case use the 'handle' property or use the function is 
what has been passed is callable.
So, preserving typeof invariants regarding 'object'/'function' is 
crucial to backward compatibility.

Likewise for arrays. In ES1-5, (typeof [] === 'object') and the 
suggested semantics of your proposal would break that.

As far as I'm concerned, just the object-literal version of function is 
a brilliant idea, no need for the additional semantics.

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120404/52e811cd/attachment.html>


More information about the es-discuss mailing list