Class: GreaterLess
- Inherits:
-
Object
- Object
- GreaterLess
- Defined in:
- lib/greater_less.rb
Overview
The GreaterLess class can be used to generate objects that represent halfopen intervals, but transparently behave as Floats. One easy way to integrate this class into your project is by requiring the greater_less string extension as follows:
require 'greater_less/string_extension'
This extension redifines the #to_f
method of the String class as follows:
class String
alias :to_f_without_greater_less :to_f
def to_f
if self =~ GreaterLess::GREATER_LESS
return GreaterLess.new(self)
end
self.to_f_without_greater_less
end
end
Now when a string starts with a greater or less sign (like for instance "> 3.45"
), the #to_f
method converts it to a GreaterLess object instead of the value 0.0
.
With this extension in place one can simply convert strings like the one above to a float like object and compare it to floats as if it were a float itself. For instance one can do the following:
>> value = ">3.45".to_f
=> > 3.45
>> value > 2.45
=> true
>> value >= 2.45
=> true
>> 2.45 > value
=> false
>> 2.45 >= value
=> false
>> value == ">3.45".to_f
=> true
>> value != 2.45
=> true
It is also possible to compare GreaterLess values with each other, so you do not have to worry about what kind of object you are dealing with in your code:
>> value1 = ">3.45".to_f
=> > 3.45
>> value2 = "< 2.45".to_f
=> < 2.45
>> value1 > value2
=> true
>> value2 > value1
=> false
Finally it is possible to apply simple arithmetics to GreaterLess objects like addition, subtraction, multiplication and division:
>> value = ">3.45".to_f
=> > 3.45
>> value + 2
=> > 5.45
>> value - 2
=> > 1.4500000000000002
>> value * 2
=> > 1.725
Inverting the object’s sign when multiplying with a negative numerical or using a GreaterLess object in the denominator is nicely dealt with:
>> value = ">3.45".to_f
=> > 3.45
>> -1 * value
=> < -3.45
>> 1 / value
=> < 0.2898550724637681
>> -1 / value
=> > -0.2898550724637681
It makes no sense to apply the operators +, -, * or / on a pair of GreaterLess objects, so an exception is raised in these cases.
All other methods are simply passed to the float value the GreaterLess object contains, so that it transparently acts like a float.
Constant Summary collapse
- GREATER_LESS =
/^[<>] ?/
Class Method Summary collapse
Instance Method Summary collapse
- #!=(numerical) ⇒ Object
- #*(numerical) ⇒ Object
- #+(numerical) ⇒ Object
- #-(numerical) ⇒ Object
- #-@ ⇒ Object
- #/(numerical) ⇒ Object
- #<(numerical) ⇒ Object
- #<=(numerical) ⇒ Object
-
#==(numerical) ⇒ Object
:doc:.
- #>(numerical) ⇒ Object
- #>=(numerical) ⇒ Object
- #coerce(object) ⇒ Object
-
#initialize(content) ⇒ GreaterLess
constructor
A new instance of GreaterLess.
- #inspect ⇒ Object
- #inverted_sign ⇒ Object
- #is_a?(klass) ⇒ Boolean
- #method_missing(*args) ⇒ Object
- #sign ⇒ Object
-
#to_f ⇒ Object
:nodoc:.
- #to_s ⇒ Object
- #value ⇒ Object
Constructor Details
#initialize(content) ⇒ GreaterLess
Returns a new instance of GreaterLess.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/greater_less.rb', line 109 def initialize(content) if content.is_a? String if content =~ /^>/ @sign = ">" elsif content =~ /^</ @sign = "<" end @float = content.gsub(/^[<>] ?/, "").to_f elsif content.is_a? Numeric @float = content.to_f else raise "Can't handle #{content.class}!" end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(*args) ⇒ Object
241 242 243 |
# File 'lib/greater_less.rb', line 241 def method_missing(*args) @float.send(*args) end |
Class Method Details
.new(content, coerce = false) ⇒ Object
100 101 102 103 104 105 106 |
# File 'lib/greater_less.rb', line 100 def new(content, coerce=false) if coerce or content =~ GREATER_LESS old_new(content) else content.to_f end end |
.old_new ⇒ Object
98 |
# File 'lib/greater_less.rb', line 98 alias :old_new :new |
Instance Method Details
#!=(numerical) ⇒ Object
170 171 172 |
# File 'lib/greater_less.rb', line 170 def !=(numerical) not self == numerical end |
#*(numerical) ⇒ Object
182 183 184 185 186 187 188 189 190 |
# File 'lib/greater_less.rb', line 182 def *(numerical) value, sign = if numerical.is_a? self.class raise "Can't handle #{self.class}!" if @sign [@float * numerical.value, @float > 0 ? numerical.sign : numerical.inverted_sign] else [@float * numerical, numerical > 0 ? @sign : inverted_sign] end GreaterLess.new("#{sign} #{value}") end |
#+(numerical) ⇒ Object
202 203 204 205 206 207 208 209 210 |
# File 'lib/greater_less.rb', line 202 def +(numerical) value, sign = if numerical.is_a? self.class raise "Can't handle #{self.class}!" if @sign [@float + numerical.value, numerical.sign] else [@float + numerical, @sign] end GreaterLess.new("#{sign} #{value}") end |
#-(numerical) ⇒ Object
212 213 214 |
# File 'lib/greater_less.rb', line 212 def -(numerical) self + -numerical end |
#-@ ⇒ Object
216 217 218 |
# File 'lib/greater_less.rb', line 216 def -@ GreaterLess.new("#{inverted_sign} -#{value}") end |
#/(numerical) ⇒ Object
192 193 194 195 196 197 198 199 200 |
# File 'lib/greater_less.rb', line 192 def /(numerical) value, sign = if numerical.is_a? self.class raise "Can't handle #{self.class}!" if @sign [@float / numerical.value, @float > 0 ? numerical.inverted_sign : numerical.sign] else [@float / numerical, numerical > 0 ? @sign : inverted_sign] end GreaterLess.new("#{sign} #{value}") end |
#<(numerical) ⇒ Object
166 167 168 |
# File 'lib/greater_less.rb', line 166 def <(numerical) numerical > self end |
#<=(numerical) ⇒ Object
178 179 180 |
# File 'lib/greater_less.rb', line 178 def <=(numerical) self == numerical or self < numerical end |
#==(numerical) ⇒ Object
:doc:
150 151 152 153 154 155 156 |
# File 'lib/greater_less.rb', line 150 def ==(numerical) if numerical.is_a? self.class @sign == numerical.sign and @float == numerical.value else false end end |
#>(numerical) ⇒ Object
158 159 160 161 162 163 164 |
# File 'lib/greater_less.rb', line 158 def >(numerical) if numerical.is_a? self.class @float >= numerical.value and [nil, ">"].include? @sign and [nil, "<"].include? numerical.sign else @float >= numerical and @sign == ">" end end |
#>=(numerical) ⇒ Object
174 175 176 |
# File 'lib/greater_less.rb', line 174 def >=(numerical) self == numerical or self > numerical end |
#coerce(object) ⇒ Object
124 125 126 127 128 129 130 |
# File 'lib/greater_less.rb', line 124 def coerce(object) if object.is_a? Numeric and not object.is_a? self.class [GreaterLess.new(object, true), self] else raise "Can't handle #{object.class}!" end end |
#inspect ⇒ Object
229 230 231 |
# File 'lib/greater_less.rb', line 229 def inspect self.to_s end |
#inverted_sign ⇒ Object
136 137 138 139 140 141 142 143 |
# File 'lib/greater_less.rb', line 136 def inverted_sign case @sign when ">" "<" when "<" ">" end end |
#is_a?(klass) ⇒ Boolean
233 234 235 236 237 238 239 |
# File 'lib/greater_less.rb', line 233 def is_a?(klass) if klass == self.class true else @float.is_a? klass end end |
#sign ⇒ Object
132 133 134 |
# File 'lib/greater_less.rb', line 132 def sign @sign end |
#to_f ⇒ Object
:nodoc:
221 222 223 |
# File 'lib/greater_less.rb', line 221 def to_f self end |
#to_s ⇒ Object
225 226 227 |
# File 'lib/greater_less.rb', line 225 def to_s "#{@sign} #{@float}" end |
#value ⇒ Object
145 146 147 |
# File 'lib/greater_less.rb', line 145 def value @float end |