添加数字时如何将 nil 值视为零?
How might I treat nil values as zero when adding numbers?
我有一个看起来像这样的方法:
def calculate_the_thing(hsh)
hsh[:x] + hsh[:y] + hsh[:z]
end
需要这样的东西:
{:x => 5, :y => nil, :z => 2, :a => 5}
我想修补一些 类 以便当 +
方法获得 nil 值时,它会将其视为零。似乎有道理。我该怎么做?
正如@jforberg 指出的那样,您可以只使用 #to_i
方法,它将 return 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
看看这个线程 - In Ruby, how does coerce() actually work? - 了解 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 开发者带来可怕的惊喜。
我有一个看起来像这样的方法:
def calculate_the_thing(hsh)
hsh[:x] + hsh[:y] + hsh[:z]
end
需要这样的东西:
{:x => 5, :y => nil, :z => 2, :a => 5}
我想修补一些 类 以便当 +
方法获得 nil 值时,它会将其视为零。似乎有道理。我该怎么做?
正如@jforberg 指出的那样,您可以只使用 #to_i
方法,它将 return 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
看看这个线程 - In Ruby, how does coerce() actually work? - 了解 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 开发者带来可怕的惊喜。