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