В RUBY, может ли метод Coerce () знать, какой оператор именно это требует помощи, чтобы помочь?

StackOverflow https://stackoverflow.com/questions/2807642

Вопрос

В Руби, похоже, что много помощи () может быть сделано

def coerce(something)
  [self, something]
end

Это, когда

3 + rational

нужен, fixnum 3 Не знает, как обрабатывать добавление рационального, поэтому он просит Rational # Coerce для получения справки, вызывая Rational.coerce (3), и этот метод экземпляра Coerce скажет абонент:

# I know how to handle rational + something, so I will return you the following:
[self, something]
# so that now you can invoke + on me, and I will deal with Fixnum to get an answer

Так что, если большинство операторов могут использовать этот метод, но не когда оно (a - b)! = (B - a) Ситуация? Может принуждать () знать, какой оператор имеется, и просто обрабатывать эти особые случаи, одновременно используя простое [я, что-то], чтобы обрабатывать все остальные случаи, где (OP b) == (b op a)? (ОП является оператором).

Это было полезно?

Решение

Точка coerce это не знать, какую операцию вы пытаетесь выполнить. Его цель - принести аргумент и self на общую почву. Кроме того, такие же операторы могут быть коммутативными в определенных классах, а не в других (Numeric#+ а также Array#+, Например), так что ваша небольшая коммутативная coerce Эксплей действительно не окупится.

Вместо того, чтобы толкать ваш coerce делать то, что он не предназначен, вы должны создать новый класс вместо этого (например, ScalarPoint, Например) и используйте его для интерфейса скалярных значений с вашим Point:

class ScalarPoint
  attr_reader :val

  def initialize(val)
    @val = val
  end

  def +(arg)
    case arg
    when Point:
      Point.new(@val + arg.x, @val + arg.y)
    when ScalarPoint:
      ScalarPoint.new(arg.val + @val)
    else
      raise "Unknown operand!"
    end
  end

  # define other operators, such as * etc

  def coerce(arg)
    return [ScalarPoint.new(arg), self] if arg.is_a?(Numeric)
    raise "Can't handle"
  end
end

а также

class Point
  def coerce(arg)
    [ScalarPoint.new(arg), self] if arg.is_a?(Numeric)
    raise "Can't handle"
  end
end

и т. д. (NB: код не тестирован)

Другие советы

Ответ на этот вопрос в том, что вы могу знать оператор, глядя на трассировку, но вам не должен сделай это.

Это не то, как был разработан механизм принудительного рубина. Как я отвечал в Ваш предыдущий вопрос, coerce следует вернуть два эквивалентных значения [a, b] Такое это a.send(operator, b) Будет работать, независимо от оператора.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top