-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
compliance of a sort optimization #2307
Comments
how would "accordingly" work if two of the strings are the same, but the underlying toStringable objects are distinct? |
That's my understanding, yes.
Empirically, no:
|
If two strings are the same, then the underlying objects are in the same equivalence class, so they sort "together", but ordered as in the original input, to satisfy the stability requirement. So an object's 'decoration' would actually be, not just its ToString result, but a pair consisting of that string and also the object's position in the input array. |
@bakkot:
So it looks to me like Chakra, JavaScriptCore, and SpiderMonkey are using the strategy of calling ToString exactly once on each item, whereas the others exhibit behavior that's consistent with the spec (calling SortCompare 3 times with 3 distinct pairs of items). |
Hah, yes, you are of course correct. Using $ eshost -sx "[{ toString(){ print(1); return '1'; } }, { toString(){ print(2); return '2'; } }, { toString(){ print(3); return '3'; } }, { toString(){ print(4); return '4'; } }].sort()"
#### Chakra, JavaScriptCore, SpiderMonkey
1
2
3
4
#### GraalJS, Hermes, V8
2
1
3
2
4
3
#### XS
1
2
2
3
3
4 |
Hmm, it seems to me that it would be compliant but I may be biased... The number of calls to The main way I could see a problem is if there was an odd number of items in the array and nothing was |
Nice catch! Some browsers cache the results (which is noncompliant with the current wording of the spec), some don't.
Firefox caches and produces |
I believe such caching is compliant. Quoting from the spec:
It doesn't say the arguments passed to As for pre-stringifying the whole list in advance, that still seems compliant because the implementation is allowed to call |
technically no calls at all is also an implementation defined sequence of calls |
That's true, it doesn't. I suspect that's an oversight, as older versions of the spec were explicit about the arguments in calls to SortCompare. Anyway, I don't think any other interpretation makes sense, given that:
An implementation could do that. That doesn't make it compliant.
Sure, but each call to SortCompare is specified to make 0 or 2 calls to
That would result in a call to So yes, a caching implementation could ensure that it always exhibited an even number of calls to ToString. But it doesn't look like they bother to do so. |
These are expressed in terms of unrealized calls to
then:
are only distinguishable by observing the |
Agreed, which is why I didn't present them as refuting your claim (that SortCompare's args aren't required to be elements of But yes, if SortCompare's args aren't required to be elements of |
In
Array.p.sort
, if_comparefn_
is*undefined*
, items are compared by comparing theirToString
results. Rather than callingToString
twice per call to SortCompare, it seems like an implementation might want to callToString
on each item exactly once, sort the resulting strings, and then arrange the original items accordingly (aka the decorate-sort-undecorate pattern).However, calls to
ToString
can be observed, and this optimization would definitely change the number of those calls (from roughly 2 n log(n) to just n). So does that mean that this optimization is non-compliant? (If so, do implementations use it anyway?)The text was updated successfully, but these errors were encountered: