joshwlewis / unitwise

Physical quantity and units of measure conversion and math for Ruby
unitwise.org
MIT License
281 stars 32 forks source link

Two questions: #to_hash and custom units #22

Open zverok opened 8 years ago

zverok commented 8 years ago

(Sorry, it's currently not an bug report/feature request, rather a questions. I am currently evaluating Unitwise for my tasks and haven't find another way to communicate.)

About #to_hash methods

As far as I know, Ruby has following convention:

Unitwise's classes currently define to_hash method, while, I think, they can not be seen as "some kind of hash".

Theoretical example of bad consequences:

def test(**options)
  p options
end

test(1) # fails with ArgumentError, which is as expected
test(Unitwise(1, 'm')) # calls test with a large hash, which is strange

Practical examle of bad consequences: when using awesome_print gem in irb (which is pretty common), it outputs those large hashes instead of compact #inspect results.

About custom units

Unitwise provides very cool, effective, well-writen and well-tested code for working with units. What could make me (and, maybe, not only me?) happy is possibility, optional, to work with any units outside the controlled dictionary. Supposed synopsys:

# Variant 1:
Unitwise(1000, 'person') # => fails
require 'unitwise/custom_units'
Unitwise(1000, 'person') # => ok

# Variant 2:
Unitwise(1000, 'person') # => fails
Unitwise::Unit.define 'person' # + some options
Unitwise(1000, 'person') # => ok

# ...and now:
Unitwise(1000, 'person') / Unitwise(1, 'km') # => Unitwise(1000 'person/km')
Unitwise(10, 'person')**2 # => Unitwise(100, 'person2')

WDYT?

joshwlewis commented 8 years ago

On the #to_hash part, I think you are correct. I'll update that in a future release.

On the person unit, that seems a little weird since it's just a count of something. That's essentially what an Integer is for. Also, UCUM defined a 1 unit code that's primarily intended for counts. I don't know your situation, but my naive stance would be to use one of those.

However, you piqued my interest with the custom units idea. I poked around a bit in irb, and I was able to get a custom unit loaded:


person_data = {:names=>"Person", :symbol=>"person", :primary_code=>"person", :scale=>{:value=>1.0, :unit_code=>"1"}, classification: "dimless"}

person = Unitwise::Atom.new(person_data)

Unitwise::Atom.all << person

Unitwise(10, "person")**2
=> #<Unitwise::Measurement value=100 unit=Pers2>

A few caveats here:

zverok commented 8 years ago

On the person unit, that seems a little weird since it's just a count of something. That's essentially what an Integer is for. Also, UCUM defined a 1 unit code that's primarily intended for counts. I don't know your situation, but my naive stance would be to use one of those.

The situation is here: https://github.com/molybdenum-99/reality I'm currently using custom (pretty naive) implementation of units (Reality::Measure):

ar = Reality.country('Argentina')
# => #<Reality::Country(Argentina)> 
ar.population
# => #<Reality::Measure(43,417,000 person)> 
ar.area
# => #<Reality::Measure(2,780,400 km²)> 
ar.population + ar.area
# ArgumentError: 43,417,000person incompatible with 2,780,400km²
ar.population / ar.area
# => #<Reality::Measure(15 person/km²)> 

In other words, I need for that project "controlled units" and "pretty output" much more than "smart conversions". And I'm curious if Unitwise is a right tool for the task.