Help draft and implement a value types with operators extension to ES5

NEW
Unassigned

Status

()

Core
JavaScript Engine
--
enhancement
9 years ago
3 years ago

People

(Reporter: Daniel Friesen, Unassigned)

Tracking

(Blocks: 1 bug)

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

9 years ago
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4) Gecko/2008111317 Ubuntu/8.04 (hardy) Firefox/3.0.4 FirePHP/0.2.1
Build Identifier: 

It would be useful to provide a method of overriding the comparison operators for objects, other than simply converting to literals using valueOf.

Currently only the string and number literals (only ones I can remember) have comparison operators (ie: <, >), while you cannot override this in a custom object.

While it is possible to use valueOf to make comparison of an object possible, ie:
var a = 0;
function Foo {};
Foo.prototype.valueOf = function() a++;
(new Foo) < (new Foo); // true

However, that sometimes has issues, primarily because + also makes use of valueOf. For example, I'm working on a HTTP library. I have a HTTPVersion object.
So that HTTPVersion gets put into requests properly, valueOf is set to:
function() 'HTTP/' + this.major + '.' + this.minor;

However, this causes issues with comparison. According to the HTTP rfc the major and minor numbers are supposed to be compared separately. Of course, I could pad the string to compare, but then I'd be sending bad HTTP versions in my headers.

Ideally I could override the [<>=]=? operators and make them compare HTTPVersions correctly.

Implementation is up to whatever the implementer thinks is best. But I've got an idea or two:
Either a single comparison function:
Foo.prototype.__compare__ = function(operator, with) {...}

Or separate them:
Foo.prototype.__lt__ = function(other) other instanceof this.constructor && this.major < other.major && this.minor < other.minor;
Foo.prototype.__gt__ = function(other) other instanceof this.constructor && this.major > other.major && this.minor > other.minor;
Foo.prototype.__equals__ = function(other) other instanceof this.constructor && this.major == other.major && this.minor == other.minor;

The <= and >= comparisons would be handled by a combination of __lt__ or __gt__ and __equals__.

Reproducible: Always
Flags: wanted1.9.2?
Version: unspecified → Trunk
Use valueOf and its hint argument to generate numbers that can be compared by relational operators, and toString to produce the canonical (per a protocol spec -- or just an informative) string:

js> o = {valueOf:function(hint){if (hint=="number")return (this.major << 16) + this.minor; return this.toString()}, toString:function()('HTTP/' + this.major + '.' + this.minor), major:4, minor:1} 
HTTP/4.1
js> p = {valueOf:function(hint){if (hint=="number")return (this.major << 16) + this.minor; return this.toString()}, toString:function()('HTTP/' + this.major + '.' + this.minor), major:4, minor:2} 
HTTP/4.2
js> o < p
true

The ES-Harmony timeframe may end up with a "value types" proposal that allows for operators to be defined. This bug isn't the place to do that work, though. The http://wiki.ecmascript.org/ wiki should have something soon, with discussion on es-discuss@mozilla.org.

/be
Value types are a hot topic. This bug isn't the place to draft a spec, but it can certainly be used for a prototype implementation of that spec. I'm generalizing it away from comparison and "overriding" to talk about value types with operators explicitly.

If an HTTP Version object really shouldn't be a value type, then based on what Mark and I agreed on last week (not written in stone, just noting it here), then that version object wouldn't be able to define operators. But there's no obvious reason why it couldn't be a value type. Anyway, lots of other use-cases beckon!

/be
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: Provide a method of overriding comparison operators → Help draft and implement a value types with operators extension to ES5
Blocks: 445178
Flags: wanted1.9.2?
(Assignee)

Updated

3 years ago
Assignee: general → nobody
You need to log in before you can comment on or make changes to this bug.