I have updated the specification such that Collator.prototype.compare is now a 
getter that returns a bound function, which is cached by the first call to the 
getter:

1. If the [[boundCompare]] internal property of this Collator is undefined, 
then:
    a. Let that be this.
    b. Let bc be a function that takes the arguments x and y and performs the 
following steps:
        i. Return the result of calling the [[Compare]] internal method of that 
with arguments x and y.
    c. Set the [[boundCompare]] internal property of this Collator to bc.
2. Return the value of the [[boundCompare]] internal property of this Collator.

[[Compare]] is what used to be Collator.prototype.compare in previous 
specification drafts.

The [[Set]] attribute is undefined.

I have no evidence that the format() methods are "likely to be routinely 
invoked as a standalone function", so I haven't changed those functions.

Norbert



On Feb 1, 2012, at 8:59 , Allen Wirfs-Brock wrote:

> 
> On Jan 31, 2012, at 4:23 PM, Nebojša Ćirić wrote:
> 
>> 31. јануар 2012. 15.50, Norbert Lindenberg 
>> <[email protected]> је написао/ла:
>> I can imagine doing this for Collator.prototype.compare because 
>> Array.prototype.sort is such a common use case for it, but why for the 
>> format() methods?
> 
> I think there is a straightforward design rule to apply in deciding whether 
> such a property should be a unbound method or a bound function.
> 
> If the value of the property is a function that is dependent upon the state 
> of its access object and the function is likely to be routinely invoke as a 
> standalone function then use a bound (or otherwise closed over the object) 
> function as the property value. 
> More simply,  if the property is routinely accessed with an expression like:
>     obj.prop
> then it should be a bound function.  If it is routinely accessed with an 
> expression like:
>    obj.prop()
> then it can be a normal method.
> 
> We have a good use case for Collator.compare that strongly suggests it should 
> be bound:
>     array.sort(col.compare)
> 
> Do we have comparable use cases for Formatter.format?
> 
>> 
>> I heard a couple of reasons for format methods to be bound:
>> 
>> 1. Can be passed as functions, thus hiding the object details
> 
> would this be routinely done?  If so it is a strong use case for a bound 
> function
>     displayDate(dt,  mdyFmtr.format)
> 
>> 2. Makes it symmetrical to compare (in case we follow Allen's advice)
>    symmetry is only important if the use cases of the two functions are 
> similar.  I assume that booth Collator and Formatter have plenty of 
> properties that are normally invoked as regular methods.
> 
>> 3. No binding gotchas for users
> There are always gotchas if you try to dissociate a function that has 
> (explicit or implicit,if built-in) this reference dependencies. That is the 
> reason for the above design rule. Retrieving a bound function is a different 
> logical operation than extracting a method implementation as an reflective 
> operation.
> 
>>  
>> We don't want to impose the overhead of creating a bound function on each 
>> call to format() unless there's a good reason...
>> 
>> Would caching first one resolve the overhead, like so (not sure about 
>> syntax):
> 
> Yes, you would definitely want to memoize the function on first access or 
> perhaps even upon object creation. 
> 
>> 
>> NumberFormat.prototype = {
>>   get format(date) {
>>      var that = this;
>>      if (that.__bound === undefined)
>>        that.__bound = function(a) { uses that; return a < b };
>>      return that.__bound;
>>   }
>> }
> 
> Yes, logically.  However a built-in implementation would use a private 
> internal state variable [[CompareFunction]] instead of a regular property.  
> An ES6 implementation in ECMAScript would use a private name property.
> 
> Alternatively, you could simply create the bound function when you 
> instantiate the  Format instancet object and make it the value of the format 
> (in this example) own property of the new instance.  However, that technique 
> would create issues if anybody ever wants to do prototypal inheritance from 
> such an instance.  For that reason, I would stick with the accessor on the 
> prototype pattern.
> 
>> 
>> Of course, doing it for one and not the other is somewhat inconsistent. And 
>> since ES 5 has Function.prototype.bind (implemented in the leading browsers 
>> except Safari), it's not hard to bind compare() without library support:
>> myArray.sort(collator.compare.bind(collator));
>> 
> 
> Do you really want a naive HTML coder to have to remember this pattern?
> 
> 
>> Yes, we should probably pick one or the other - go jQuery route and force 
>> developers to .bind manually, or any other library where they either bind 
>> for the users or provide two versions of the same method (one bind the other 
>> one not).
> 
> For these cases,  I don't see why you would need the unbound method.  Such a 
> unbound method is really only useful it you are going to move it to another 
> object and this isn't any particular reason why that should be expected to 
> work in this scenario.  Even though the function is bound you can still say:
> 
>   col.compare(a,b)
> 
> if you want to invoke it using a method invocation style
> 
> Allen

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to