molybdenum-99 / reality

Comprehensive data proxy to knowledge about real world
MIT License
818 stars 43 forks source link

Measure: time math #12

Open zverok opened 8 years ago

zverok commented 8 years ago

Seems to be implemented in multiple other libraries, so just use them/import code:

Measure(1, 'h').since # => Time.now + 1 hour
Measure(1, 'h').ago   # => Time.now - 1 hour

...and so on.

ptolemybarnes commented 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.

zverok commented 8 years ago

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):

# 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 
zverok commented 8 years ago

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)

zverok commented 8 years ago
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.

ptolemybarnes commented 8 years ago

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. :)

zverok commented 8 years ago

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!