Skip to content
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

More idiomatic comparison methods #6

Open
ptomato opened this issue Feb 12, 2021 · 5 comments
Open

More idiomatic comparison methods #6

ptomato opened this issue Feb 12, 2021 · 5 comments

Comments

@ptomato
Copy link
Collaborator

ptomato commented Feb 12, 2021

Summary of discussion from tc39/proposal-temporal#1086 and meeting minutes:

The Temporal.(type).compare() static methods have confusing parameter order, in order for them to be able to be used as the comparator function for Array.prototype.sort().

A suggestion that's come up several times is that Temporal types could have more idiomatic methods named something like lessThan(), earlierThan(), isBefore(), isSameOrAfter(). Although these would duplicate the functionality of compare(), they would make user code much easier to read.

For example:

// proposed
function afterKidsBedtime(time) {
  return time.greaterThan('20:30');
}
// current
function afterKidsBedtime(time) {
  return Temporal.PlainTime.compare(time, '20:30') > 0;
}

There was a work-in-progress at tc39/proposal-temporal#1074 on which a proposal in this repository can be based.

Sets of names that were proposed so far:

  1. greaterThan(), lessThan(), greaterEquals(), lessEquals()
  2. greater(), lesser(), greaterEquals(), lesserEquals()
  3. greater(), lesser(), greaterOrEquals(), lesserOrEquals()
  4. greater(), less(), greaterEquals(), lessEquals()
  5. greater(), less(), greaterOrEquals(), lessOrEquals()
  6. gt(), lt(), ge(), le()
  7. earlier(), later(), earlierEquals(), laterEquals()

Advantages:

The meaning of the return value of compare(a, b) has been confusing since it was first introduced in C, because you have to think carefully about whether 1 means a > b or b < a. It can't be read left-to-right.

An isSame() method could, in addition, implement equality based on the internal ISO-calendar slots of the Temporal object, without taking the calendar into account, which makes it fulfill a different function from equals().

Concerns:

Such an API might become useless if operator overloading is ever added to the language, at which point the comparison operators could simply be used.

Names like greaterThan() are closely tied to English grammar and so may only improve the issue for English speakers.

A problem with names implying "before" or "after" is that due to time zones, a wall-clock time that is "greater than" another wall-clock time may not actually be "after" it. These names also wouldn't be consistent if similar methods were added to Temporal.Duration.

Prior art:

  • Moment (including the ability to specify the granularity: isSame('day')
  • ThreeTen / java-time / js-joda: time1.isAfter(time2)
  • TBD

Constraints / corner cases:

TBD

@Louis-Aime
Copy link

I am in favour of qualifiers that refer to time, i.e. .earlier() - .later() or .before() - .after(), or variants like .isEarlier() etc. This would assert that real instants are compared, not wall clock indications.

@justingrant
Copy link

There was discussion in the chat during today's TC39 plenary meeting that was related to this issue. Capturing feedback here. @rbuckton, feel free to expand/clarify. Thanks!

rbuckton: My only qualm with Temporal is how hard it is to use for its main purpose (date arithmetic, specifically relational comparison).

rbuckton: Temporal.Instant.compare(inst, Temporal.Now.instant()) > 0 is not a win, imo

justingrant: Is this the lack of isEarlier/isLater APIs? Or concerns about how compare can return 0 for values where equals will return false? If the former, there's a clear path to add those APIs in a follow-up proposal.

rbuckton: A.isEarlier(B) is a bit harder to conceptualize than A < B, imo. And is very English-focused vs. compareTo.

rbuckton: compareTo you learn once and let math take care of the rest. A non-native-English speaker might need to refer to which is which (earlier/later)

@ptomato FYI

@bakkot
Copy link

bakkot commented Sep 6, 2022

A small note on naming: the W3C tag guidelines recommend the use of the "is" prefix for methods which ask a boolean question about their argument.

I also favor "isBefore" or "isEarlierThan" or similar.

@ptomato
Copy link
Collaborator Author

ptomato commented Nov 2, 2022

Another suggestion (tc39/proposal-temporal#517 (comment)) is that although it would be bad to have all Temporal types return a value from their valueOf() methods, it might be feasible to have Temporal.Instant.prototype.valueOf and Temporal.ZonedDateTime.prototype.valueOf stop throwing an exception and return a BigInt instead.

(Note that would preclude ever increasing the resolution of exact times beyond nanoseconds. Although given how divisive nanoseconds has proven to be, maybe it's the case that sub-nanoseconds are just too far removed from human perception to be useful...)

@bergus
Copy link

bergus commented Nov 3, 2022

Note that would preclude ever increasing the resolution of exact times beyond nanoseconds.

In that future where we need sub-nanosecond precision, valueOf() could return a BigDecimal value which is comparable with a BigInt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants