Logical operators don't use valueOf()

Filip Pizlo fpizlo at apple.com
Sun Sep 8 13:56:52 PDT 2013


Never having a toBoolean hook would be quite constraining.  The example from that e-mail involved:

> var huh = (obj || foo) && bar;

And the problem is that a valueOf or toBoolean hook on 'obj' could result in it being called multiple times, and since the hook is written in JS it could be stateful and it could change its mind.  The execution steps could be:

1) Call toBoolean on obj.  Lets say this time it returns true.
2) Skip evaluation of 'foo'
3) The expression (obj || foo) now has the value of obj, and *not* the value it returned from toBoolean - since we are doing value preservation.
4) Now we are evaluate obj && bar, which means that we need to again call toBoolean on obj.  At this point it may return false, just for fun.

We have two choices:

A) Reject the notion that 'obj' appearing once in the original source results in multiple calls to some hook on 'obj' (valueOf, toBoolean, whatever).
B) Allow multiple calls along with all that it entails.

I like the idea of B because as weird as it is, the pros outweigh the cons, in my own accounting.  I hope I didn't miss any pros or cons.

Pro:

+ Allows users to easily create value-like objects.  I think value-like objects are a wonderful abstraction and it would be great to allow it.
+ Solves the problem that Brendan alluded to: "Without reopening this ancient ES1 conflict, I hope to find a solution that does not complicate the semantics with memoization of implicit conversion results."  This is a solution and it doesn't involve memoization.
+ Creates consistency with other operators in the language, which do allow for value conversion hooks.
+ Systems often have APIs or language features that result in a surprising and sometimes even non-deterministic number of calls to a user-provided callback, where that callback may be stateful even though for any sensible use you're supposed to make it stateless.  Java's hashCode()/equals()/compare() when used with any built-in collections have this behavior. And it turns out that while yucky, it's not a big deal.  JavaScript's sort is another example of this.

Con:

- You can write a program and get hilarious results.
- It reopens an ancient ES1 conflict that was thought to have been resolved.
- It is a substantial change to the semantics of a fundamental language operation.  There is an elegance to saying that ToBoolean is pure.  We would break that purity.
- It will be hell for JS optimizing JITs.

I think that the pros are much mightier than the cons here.  Creating value-like objects would be awesome.  Sure, you can get it wrong by making your toBoolean hook stateful - but I've rarely seen Java code get tripped up on statefulness of hashCode/equals/compare.  I mean, it does happen sometimes - but not enough for anyone to really care.  On the other hand, I can't get passionate about any of the cons.  Of course you can write a program and get weird results - that's true of any Turing-complete language; the relevant question is: how likely are users to encounter the dark corners?  In this case I don't see it as being very likely.  I can't get passionate about an ES1 conflict because I wasn't there.  I also don't think you can achieve nice value types without accepting that some currently pure language features will become impure.  Finally, I don't think that the difficulty of implementation for JS language implementors should be a factor.

Note that I didn't include compatibility in the Con list - maybe I'm wrong but it feels like there ought to be a way of adding an API to register a toBoolean hook such that if you don't call the hook you're *guaranteed* to get the old behavior.  But this does imply that we use a new hook (something like a toBoolean method) rather than saying that ToBoolean calls valueOf or toString.

So, sorry to push on this ancient decision - but it really feels like we could get a lot of win from reconsidering it.

-Filip


On Sep 8, 2013, at 12:43 PM, Brendan Eich <brendan at mozilla.com> wrote:

> Did you read my reply on this point?
> 
> https://mail.mozilla.org/pipermail/es-discuss/2013-September/033234.html
> 
> Anything unclear?
> 
> /be
> 
>> Marius Gundersen <mailto:gundersen at gmail.com>
>> September 8, 2013 3:47 AM
>> So how about implementing toBoolean as an overridable method, which is called whenever !, || or && are used. This way an objec has three method for converting it into a primitive; toString, toValue and toBoolean.
>> 
>> Marius Gundersen
>> 
>> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130908/d8cdc530/attachment-0001.html>


More information about the es-discuss mailing list