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

Make units of same type comparable #58

Open
sargunv opened this issue Jan 9, 2025 · 6 comments
Open

Make units of same type comparable #58

sargunv opened this issue Jan 9, 2025 · 6 comments
Labels
blocked Something is blocking this issue from being worked on. enhancement New feature or request
Milestone

Comments

@sargunv
Copy link

sargunv commented Jan 9, 2025

It would be nice for units to implement Comparable with other units of the same type. I currently have a function that takes Set<LengthUnit> and then does some work with the units in order of size. To sort them, I have to do units.sortedBy { it.nanometerScale }. If the units support Comparable, I could just do units.sorted().

CleanShot 2025-01-08 at 23 58 41@2x

happy to PR this if it's acceptable

@kevincianfarini
Copy link
Owner

kevincianfarini commented Jan 9, 2025

@kevincianfarini
Copy link
Owner

kevincianfarini commented Jan 9, 2025

Oh, sorry, I see! You want the actual units to implement comparable.

@kevincianfarini
Copy link
Owner

kevincianfarini commented Jan 9, 2025

I think this depends on the outcome of #42. The design I'm thinking about will likely end up being similar to TemperatureUnit which would make unit being comparable difficult or possibly even invalid for some types.

Consider temperature: is a degree Fahrenheit larger, smaller, or the same as a degree Celsius? Likewise, is a degree Celsius larger, smaller or the same as a degree Kelvin?

At some degrees, a degree Celsius might be exactly equivalent to a degree Fahrenheit (-40°F/°C), but at much larger magnitudes their scale differs greatly. I think in this case it might be impossible to compare the actual units themselves since they don't scale linearly.

image

Should that prohibit us from implementing Comparable on other units? I don't know. I'm open to ideas under the assumption that they might break in the future. I'd hate to require consumers of this library implement Comparable on their custom units only to find out my naive assumption about Power, Length, Energy, etc always being linear scales was incorrect.

@sargunv
Copy link
Author

sargunv commented Jan 9, 2025

Are there other quantities where there exist units that start counting below zero?

Nothing comes to mind, but I think for any linear units, it's reasonable to either:

  • Implement Comparable only on those units that always start at zero (like length)
  • Implement comparable on all of them, document it's based on the "size" of the unit, even though it's maybe not that useful to sort Celsius and Fahrenheit.
    • Similarly, it's not that useful to sort Feet and Meters, but is useful to sort Feet and Miles or Meters and Kilometers

The constraint I could see: are there some units that don't scale linearly at all? These would be the only ones that don't have a distinct "size" and therefore unclear how they should sort. If we expect to support such things, then yeah I'd avoid implementing Comparable on the unit.

@kevincianfarini
Copy link
Owner

I think if we were to offer this, we wouldn't offer is on TemperatureUnit and we'd implement it globally instead of requiring inheritors to implement it. Something like:

abstract class LengthUnit : Comparable<LengthUnit> {

  abstract fun convertThisToNanometers(quantity: Long): Long

  override fun compareTo(other: LengthUnit): Int {
    val thisScale = convertThisToNanometers(2L) - convertThisToNanometers(1L)
    val otherScale = other.convertThisToNanometers(2L) - other.convertThisToNanometers(1L)
    return thisScale.compareTo(otherScale)
  }
}

@kevincianfarini kevincianfarini added this to the 0.2.0 milestone Jan 9, 2025
@sargunv
Copy link
Author

sargunv commented Jan 9, 2025

instead of requiring inheritors to implement it

that's reasonable I think. if you want to prevent inheritors from being able to implement it, I think you'd need to make LengthUnit an abstract class and compareTo a final override fun. If you just want to not require them to implement it, you can keep it as an interface and provide a default override fun impl.

@kevincianfarini kevincianfarini added enhancement New feature or request blocked Something is blocking this issue from being worked on. labels Jan 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Something is blocking this issue from being worked on. enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants