1

I've submitted a pull request, which modifies the Matrix class so that additions can be performed with real numbers:

Matrix[ [25, 93], [-1, 66] ] + 5

The Matrix class has a method +(), which is called in this case.

I would also like users to be able to change the order of the operation to

5 + Matrix[ [25, 93], [-1, 66] ]

The Matrix class seems to support this order of operation for the *() method and I'm unsure how to implement this for the +() method.

4

2 回答 2

2

Coercion is handled with coerce method. This method is to return two elements for which given operator/method is to be retried. Matrix defines coerce like:

def coerce(other)
  case other
  when Numeric
    return Scalar.new(other), self
  else
    raise TypeError, "#{self.class} can't be coerced into #{other.class}"
  end
end

Note however that it is not changing the order of the operands, but rather converts numeric value into a Scalar class. Hence, ruby seeing 5 + Matrix[...] will execute Scalar.new(5) + Matrix[...].

Scalar class is defined within the same file and defines its own set of operators, including + and '-'. So what you need to do is get rid of line Scalar.Raise ErrOperationNotDefined, "+", @value.class, other.class and enforce your code here, for example with other + self

于 2014-07-27T19:01:43.700 回答
2

这对于评论来说太长了,它是一种答案。但是,我不想解释#coerce任何人都可以从文档中阅读的工作原理,而是想告诉你,不要这样做。我的意思是

  1. 不要Matrix#+通过向所有元素添加数字来重载,并且
  2. 不要修改Matrix#coerce.

1. 的原因是您认为您正在添加一项功能。但你也失去了一些东西。矩阵通常只能与相同维度的其他矩阵相加。如果你犯了一个错误,尝试对不同维度的矩阵求和,或者尝试将一个矩阵与一些不相关的对象求和,你会得到一个错误。这个错误是对程序员的服务。这是一个受欢迎的提醒,它使我们能够及早发现我们犯了一个错误,我们正在尝试将不兼容的对象添加到矩阵中。这个错误使我们能够及早发现问题。如果你开始重载Matrix#+,你会获得新的功能,但你也会失去警告,语言变得更加脆弱。如果你真的想给每个元素添加一个数字,定义一个新的方法,比如


class Matrix
  def add_to_each n
    self + self.map { n }
  end
end

至于 2.,您又一次使 2 个对象变得脆弱:Matrix::Scalar和数字对象。你认为你是在做一项服务,使之Matrix更有用。但是写作

Matrix[[1, 2], [3, 4]].map { |e| e + 5 }

一点都不难。Imo,通过重载使这种语法变甜+是一种净损失。我知道你已经完成了这项工作,但是将它作为一个 gem 发布,不要用这个特性蠕变污染核心。

于 2014-07-27T20:04:25.917 回答