理解强制

时间:2014-07-27 18:33:58

标签: ruby matrix coercion

我提交了pull request,修改了Matrix类,以便可以使用实数进行添加:

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

Matrix类有一个方法+(),在这种情况下调用它。

我还希望用户能够将操作的顺序更改为

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

Matrix class似乎支持*()方法的此操作顺序,我不确定如何为+()方法实现此操作。

2 个答案:

答案 0 :(得分:2)

使用coerce方法处理强制。此方法返回两个要重试给定运算符/方法的元素。 Matrix定义coerce,如:

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

但请注意,它不会更改操作数的顺序,而是将数值转换为Scalar类。因此,看到5 + Matrix[...]的红宝石将执行Scalar.new(5) + Matrix[...]

Scalar类在同一个文件中定义,并定义了自己的一组运算符,包括+和' - '。所以你需要做的是摆脱行Scalar.Raise ErrOperationNotDefined, "+", @value.class, other.class并在这里强制执行你的代码,例如使用other + self

答案 1 :(得分:2)

评论太长了,这是一种答案。但是,我不想解释#coerce如何工作,任何人都可以从文档中读到,我想告诉你,不要这样做。就此而言,我的意思是

  1. 不要为所有元素添加数字Matrix#+重载,
  2. 不要修改Matrix#coerce
  3. 1.的原因是您认为您正在添加功能。但你也失去了一些东西。矩阵通常只能与相同维度的其他矩阵相加。如果你犯了一个错误并尝试总结不同维度的矩阵,或者试图用一些不相关的对象来总结一个矩阵,你就会得到一个错误。此错误是程序员的服务。这是一个受欢迎的reminer,它允许我们尽早发现我们犯了一个错误,我们正在尝试将不兼容的对象添加到矩阵中。此错误允许我们尽早发现问题。如果你开始超载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,通过重载+来改变这种语法是一种净损失。我知道你已经完成了这项工作,但是把它作为一个宝石发布,不要用这个特征蠕变污染核心。