在添加数字时,我如何将 nil 值视为零



我有一个看起来像这样的方法:

def calculate_the_thing(hsh)
  hsh[:x] + hsh[:y] + hsh[:z]
end

它需要这样的东西:

{:x => 5, :y => nil, :z => 2, :a => 5}

我想修补一些类,以便当 + 方法获得 nil 值时,它会将其视为零。似乎很合理。我该怎么做?

正如@jforberg指出的那样,您可以使用 #to_i 方法,该方法将返回 0 表示 nil。

def calculate_the_thing(hsh)
  hsh[:x].to_i + hsh[:y].to_i + hsh[:z].to_i
end

或者,您也可以使用自动默认值定义哈希...

hsh = Hash.new{0}

但是,如果您有一个方法,该方法显式地将nil作为将覆盖默认值的哈希值。

你需要

猴子修补Nilclass以强制nil为整数。 这是代码:

class NilClass
  def coerce(n)
    return [0, n] if n.is_a? Numeric
    super
  end
end
1 + nil
#=> 1

看看这个线程 - 在 Ruby 中,coerce(( 实际上是如何工作的?- 理解coerce的概念。


但是,上面的代码存在一个问题:

nil + 1
#=> undefined method `+' for nil:NilClass (NoMethodError)

要解决此问题,您必须在NilClass上定义+方法

class NilClass
  def +(param)
    param  + self
  end
end
nil + 1
#=> 1

如果我们尝试冒险并尝试:

nil * 10
#=> undefined method `*' for nil:NilClass (NoMethodError)
通过

冒险,让我们通过实现我们自己的method_missing处理程序来处理所有这些undefined method

class NilClass
  def method_missing m, *args, &block
    args.first.send(m, self, &block) if args.size == 1
  end
end
p nil * 1
#=> 0

接下来,让我们尝试:

nil + "hello"
# '+': can't convert NilClass to String (NilClass#to_str gives NilClass) (TypeError)

让我们也解决这个问题

class NilClass
  def to_str
    ""
  end
end
nil + "hello"
#=> "hello"

接下来,让我们试试这个:

nil + [1,2,3]
#=> '+': can't convert NilClass to Array (NilClass#to_ary gives NilClass) (TypeError)

让我们修复它:

class NilClass
  def to_ary
    []
  end
end
nil + [1,2,3]
#=> [1, 2, 3]

我们现在有这个版本的NilClass

class NilClass
  def coerce(n)
    return [0, n] if n.is_a? Numeric
    super
  end
  def method_missing m, *args, &block
    args.first.send(m, self, &block) if args.size == 1
  end
  def to_str
    ""
  end
  def to_ary
    []
  end
end

注意::上面的代码表明您可以执行要执行的操作。 但是,这应该仅用于实验和学习目的。 在所有操作中nil表现得像其他操作数确实是不可行的,你最终会无休止地修补猴子NilClass。因此,最好远离这种猴子补丁,以避免给未来将维护您的代码的 Ruby 主义者带来可怕的惊喜。

最新更新