rubysolo/dentaku

Comparators should(?) cast to numeric

systemed opened this issue · 1 comments

#119/#120 cast strings to numeric values for functions, given that this behaviour already works with addition and similar operators.

This leaves comparators as an odd one out. 3 < "5" returns nil, as does 5=="5".

However, we don't want to always cast to numeric, as == and != (and, to a lesser extent, < etc.) are also valid operators to apply to two strings. So it would make sense (in my eyes) to cast both values to numeric only if one of them is already numeric.

This code works for me:

class Comparator < Operation
  private
  def cmp(op,context)
    numeric = left.type==:numeric || right.type==:numeric
    l = numeric ? Dentaku::AST::Function.numeric(left.value(context) ) : left.value(context)
    r = numeric ? Dentaku::AST::Function.numeric(right.value(context)) : right.value(context)
    l.send(op, r)
  end
end
class LessThan           < Comparator; def value(context = {}); super() { cmp('<' ,context) } end end
class LessThanOrEqual    < Comparator; def value(context = {}); super() { cmp('<=',context) } end end
class GreaterThan        < Comparator; def value(context = {}); super() { cmp('>' ,context) } end end
class GreaterThanOrEqual < Comparator; def value(context = {}); super() { cmp('>=',context) } end end
class Equal              < Comparator; def value(context = {}); super() { cmp('==',context) } end end
class NotEqual           < Comparator; def value(context = {}); super() { cmp('!=',context) } end end

If this would be useful I can prepare a PR for it.

Yes, this makes sense to me!