Class: Stick::Units::Unit
- Inherits:
-
Object
- Object
- Stick::Units::Unit
- Defined in:
- lib/stick/units/base.rb
Overview
This class represents a Unit. A Unit uses a given Converter with a number of registered units in which it can be expressed. A Unit is the product of the powers of other units. In principle, these need not be integer powers, but this may cause problems with rounding. The following code for example returns false
:
Unit.new(:m => 0.1) * Unit.new(:m => 0.2) == Unit.new(:m => 0.3)
Units can be multiplied, divided, and raised to a given power. As an extra, 1 can be divided by a Unit.
Examples:
Unit.new(:mi => 1, :s => -1) ** 2 # => mi**2/s**2
Unit.new(:mi => 1, :s => -1) * Unit.new(:s => 1, :usd => -1) # => mi/usd
Unit.new(:mi => 1, :s => -1, Converter.converter(:uk)) *
Unit.new(:s => 1, :usd => -1, Converter.converter(:us)) # => TypeError
1 / Unit.new(:mi => 1, :s => -1) # => s/mi
Instance Attribute Summary collapse
-
#units ⇒ Object
readonly
Returns the value of attribute units.
Instance Method Summary collapse
-
#*(other) ⇒ Object
Multiplies with the given Unit.
-
#**(p) ⇒ Object
Raises to the given power.
-
#/(other) ⇒ Object
Divides by the given Unit.
-
#==(other) ⇒ Object
(also: #eql?)
Returns
true
iff the two units are equals, i.e., iff they have the same exponent for all units, and they both use the same Converter. -
#coerce(other) ⇒ Object
:nodoc:.
-
#compatible_with?(other) ⇒ Boolean
Returns
true
iff this Unit is compatible with the given Unit. - #hash ⇒ Object
-
#initialize(units = {}, converter = nil) ⇒ Unit
constructor
Creates a new (composite) Unit.
- #method_missing(m, *args, &blk) ⇒ Object
- #simplify ⇒ Object
-
#to_s ⇒ Object
(also: #inspect)
Returns a human readable string representation.
-
#to_unit(converter = nil) ⇒ Object
Returns
self
. -
#unitless? ⇒ Boolean
Returns
true
iff this Unit has all exponents equal to 0.
Constructor Details
#initialize(units = {}, converter = nil) ⇒ Unit
Creates a new (composite) Unit. It is passed a hash of the form {:unit => exponent}
, and the Converter to use.
Examples:
Unit.new(:m => 1, :s => -1, Converter.converter(:uk)) # => m/s
Unit.new(:mi => 1, :s => -2) # => mi/s**2
See also Converter, Converter.converter
206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/stick/units/base.rb', line 206 def initialize(units = {}, converter = nil) conv = proc { converter ||= Units::Converter.current } if units.is_a? ::String @units = decode_string(units, conv) else @units = {} units.each_pair do |k, v| k = conv[].base_unit(k.to_sym) if not k.is_a? Units::BaseUnit @units[k] = v end end normalize_units end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *args, &blk) ⇒ Object
291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/stick/units/base.rb', line 291 def method_missing(m, *args, &blk) if args.length == 1 args[0] = (Units::Converter.converter(args[0]) rescue nil) if not args[0].is_a? Units::Converter return self * Units::Unit.new({m => 1}, args[0]) if args[0] && args[0].registered?(m) elsif (Units::Converter.current.registered?(m) rescue false) raise ::ArgumentError, "Wrong number of arguments" if args.length != 0 return self * Units::Unit.new({m => 1}, Units::Converter.current) end ::Exception.with_clean_backtrace("method_missing") { super } end |
Instance Attribute Details
#units ⇒ Object (readonly)
Returns the value of attribute units.
194 195 196 |
# File 'lib/stick/units/base.rb', line 194 def units @units end |
Instance Method Details
#*(other) ⇒ Object
Multiplies with the given Unit.
230 231 232 |
# File 'lib/stick/units/base.rb', line 230 def *(other) do_op(:*, :+, other) end |
#**(p) ⇒ Object
Raises to the given power.
221 222 223 224 225 226 227 |
# File 'lib/stick/units/base.rb', line 221 def **(p) result = {} @units.each_pair do |u, e| result[u] = e * p end Units::Unit.new(result) end |
#/(other) ⇒ Object
Divides by the given Unit.
235 236 237 |
# File 'lib/stick/units/base.rb', line 235 def /(other) do_op(:/, :-, other) end |
#==(other) ⇒ Object Also known as: eql?
Returns true
iff the two units are equals, i.e., iff they have the same exponent for all units, and they both use the same Converter.
255 256 257 |
# File 'lib/stick/units/base.rb', line 255 def ==(other) other.is_a?(Units::Unit) && other.units == units end |
#coerce(other) ⇒ Object
:nodoc:
244 245 246 247 |
# File 'lib/stick/units/base.rb', line 244 def coerce(other) # :nodoc: return [Units::Unit.new({}), self] if other == 1 Units::Converter.coerce_units(self, other) end |
#compatible_with?(other) ⇒ Boolean
Returns true
iff this Unit is compatible with the given Unit. This is less strict than equality because for example hours are compatible with seconds (“we can add them”), but hours are not seconds.
268 269 270 271 |
# File 'lib/stick/units/base.rb', line 268 def compatible_with?(other) conv1, conv2 = Units::Converter.coerce_units(self, other) conv1.units == conv2.units end |
#hash ⇒ Object
261 262 263 |
# File 'lib/stick/units/base.rb', line 261 def hash @units.to_a.map { |e| e.hash }.hash end |
#simplify ⇒ Object
249 250 251 |
# File 'lib/stick/units/base.rb', line 249 def simplify Units::Converter.simplify_unit(self) end |
#to_s ⇒ Object Also known as: inspect
Returns a human readable string representation.
274 275 276 277 278 279 280 281 282 |
# File 'lib/stick/units/base.rb', line 274 def to_s numerator = "" denominator = "" @units.each_pair do |u, e| e_abs = e > 0 ? e : -e # This works with Complex too (e > 0 ? numerator : denominator) << " #{u.to_s}#{"**#{e_abs}" if e_abs != 1}" end "#{numerator.lstrip}#{"/" + denominator.lstrip if not denominator.empty?}" end |
#to_unit(converter = nil) ⇒ Object
Returns self
.
285 286 287 |
# File 'lib/stick/units/base.rb', line 285 def to_unit(converter = nil) self end |
#unitless? ⇒ Boolean
Returns true
iff this Unit has all exponents equal to 0.
240 241 242 |
# File 'lib/stick/units/base.rb', line 240 def unitless? @units.empty? end |