Open zverok opened 8 years ago
Hey @zverok, really cool gem you have here. I'm interested in getting involved. A question on this: why not use an existing gem to handle units rather than roll your own? At a glance, this one might do.
Hey @ptolemybarnes! It's REALLY complicated question, faithfully.
For one, current Reality state is compact yet useful prototype. I'd be really happy to use any other library instead of building my owns... But it happens so that existing libraries (of course, I evaluated ruby-units, as well as unitwise, ruby-measurement and several others) are powerful in some areas while helpless in others, that I feel as important.
For example, most of existing libraries are hard at extending their units system, while I (currently) think it is necessary:
require 'reality'
Reality::Entity('Ukraine').population
# => #<Reality::Measure(42,800,501 person)>
require 'ruby-units'
Unit.new(42_800_501, 'person')
# => ArgumentError: '42800501 person' Unit not recognized
I REALLY want to use something external, and still thinking hard about it. If somebody (wink-wink) will do this carefully, I'd be happy!
My targets for Ideal Eternal Reality::Measure
(either constructed independently, or used from external library, or being wrapper on several libraries):
inspect
(currently, I think our measure inspect looks more consistent than ruby-unit's one and more concise than unitwise's one, but my mind can be changed with good arguments)1m + 2m
, 1km / 1h
and so on)1km + 100m
and explicitly, like 1km.to(m)
)1km
vs 1kilometer
# ruby-units: nope
(Unit.new(1, 'm') / Unit.new(2, 'm')).class
# => RubyUnits::Unit
# unitwise: nope
(Unitwise(1, 'm') / Unitwise(2, 'm')).class
# => Unitwise::Measurement
# reality: yep
(Reality::Measure(1, 'm') / Reality::Measure(2, 'm')).class
# => Rational
neither ruby-units, nor unitwise can provide extended functionality for "time measurement" units...
ok, looking closer at it, ruby-units seems to can... though, by extending core classes. which is pretty questionable practice for widely-used gems (unless this gem is rails/active_support, but it's not the case)
require 'ruby-unit'
Unit.new(1000, 'm') / Unit.new(1, 'm')
# => 1000 --- ok
Unit.new(1, 'km') + Unit.new(1, 'm')
# => 1.001 km --- ok
Unit.new(1, 'km') / Unit.new(1, 'm')
# => 1 km/m --- NOT OK
...and so on, and so on.
I see. I can't see how you can have complete extensibility and be able to convert between measurements in like units though. For example, if we want to do:
Measure.new(1, 'km') + Measure.new(1, 'm')
Then the units 'km' and 'm' have to somehow know about each other so that they can know that they're compatible. But the way units are being created at the moment doesn't allow for that. Please correct me on this if I'm wrong; I haven't spent that much time exploring the code yet. :)
Yes, currently Measure
is kind of "early draft" (as almost everything inside). I haven't made up my mind yet of how to provide convertability, there are three major options, as I can see:
Maybe even on-the-fly units is not what we want, but rather predefined list (which should be, though, larger than "just physical units").
So, I'm open to discussions and proposals!
Seems to be implemented in multiple other libraries, so just use them/import code:
...and so on.