rubysolo / dentaku

math and logic formula parser and evaluator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`dentaku + ruby-units`: Let `dentaku` defer some or all operations to custom class

abhinavc opened this issue · comments

Hi @rubysolo,
First, thanks for a wonderful gem. It is just what I was looking for.

I have, however, have run into a tiny issue. I'm trying to do calculations w/ physical quantities - expressed using ruby-units gem. ruby-units overloads +, -, * and / operators - amongst others.

Everything works fine - except /. So, something like

calc = Dentaku::Calculator.new 
a = Unit.new(1, 'N')
b = Unit.new(1, 'm^2') 
pressure = calc.evaluate('a/b', a: a, b: b) # should return 1 N/m^2

throws a BigDecimal: invalid value for BigDecimal(): "1 m^2" (ArgumentError) exception.
But if I comment out def value in class Division < Arithmetic (ast/arithmetic.rb)

class Division < Arithmetic
      def operator
        :/  
      end 

=begin
      def value(context = {}) 
        y = right.value(context)
        r = decimal(cast(right.value(context)))
        raise Dentaku::ZeroDivisionError if r.zero?

        cast(cast(left.value(context)) / r)
      end
=end 

      def self.precedence
        20  
      end 
end 

then dentaku does not try to convert the value and ruby-units does the actual calculation .

Hence I was wondering if dentaku could be configured to defer calculations to a user-defined custom class. Maybe have an config/initializers/dentaku.rb with either of the following options:

  1. config.use_user_class true (default = false) -> dentaku wouldn't even try to do BigDecimal conversion, or
  2. config.use_classes [<list of class names>] -> dentaku will first try these and if operator fails, then defer to it's own default behaviour

The onus of overloading operators would be on the user class

I've only done a cursory reading of the code. You may have a more robust alternative to offer. Nevertheless, if this could be done formally, then I wouldn't have to continue with my hack.

Thanks
Abhinav.