如何处理 Ruby 中自动激活哈希的组合 []+= ?
为了实现 Ruby 哈希的自动激活,可以使用以下类
class AutoHash < Hash
def initialize(*args)
super()
@update, @update_index = args[0][:update], args[0][:update_key] unless
args.empty?
end
def [](k)
if self.has_key?k
super(k)
else
AutoHash.new(:update => self, :update_key => k)
end
end
def []=(k, v)
@update[@update_index] = self if @update and @update_index
super
end
def few(n=0)
Array.new(n) { AutoHash.new }
end
end
该类允许执行以下操作
a = AutoHash.new
a[:a][:b] = 1
p a[:c] # => {} # key :c has not been created
p a # => {:a=>{:b=>1}} # note, that it does not have key :c
a,b,c = AutoHash.new.few 3
b[:d] = 1
p [a,b,c] # => [{}, {:d=>1}, {}] # hashes are independent
有 这个类的更高级的定义Joshua提出,这对我来说有点难以理解。
问题
有一种情况,我认为新类可以改进。以下代码失败并显示错误消息 NoMethodError: undefined method '+' for {}:AutoHash
a = AutoHash.new
5.times { a[:sum] += 10 }
您将如何处理它?可以定义[]+=
运算符吗?
相关问题
In order to implement auto-vivification of Ruby hash, one can employ the following class
class AutoHash < Hash
def initialize(*args)
super()
@update, @update_index = args[0][:update], args[0][:update_key] unless
args.empty?
end
def [](k)
if self.has_key?k
super(k)
else
AutoHash.new(:update => self, :update_key => k)
end
end
def []=(k, v)
@update[@update_index] = self if @update and @update_index
super
end
def few(n=0)
Array.new(n) { AutoHash.new }
end
end
This class allows to do the following things
a = AutoHash.new
a[:a][:b] = 1
p a[:c] # => {} # key :c has not been created
p a # => {:a=>{:b=>1}} # note, that it does not have key :c
a,b,c = AutoHash.new.few 3
b[:d] = 1
p [a,b,c] # => [{}, {:d=>1}, {}] # hashes are independent
There is a bit more advanced definition of this class proposed by Joshua, which is a bit hard for me to understand.
Problem
There is one situation, where I think the new class can be improved. The following code fails with the error message NoMethodError: undefined method '+' for {}:AutoHash
a = AutoHash.new
5.times { a[:sum] += 10 }
What would you do to handle it? Can one define []+=
operator?
Related questions
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
ruby 中无法定义
[]+=
方法。当您键入时会发生的情况是,
[]
和[]=
方法都会在x
上调用(以及+
> 在x[y]
上调用,在本例中是一个AutoHash
)。我认为处理这个问题的最好方法是在 AutoHash 上定义一个 + 方法,它只会返回它的参数。这将使AutoHash.new[:x] += y
适用于几乎任何类型的y
,因为y.class< 的“空”版本/code> (
''
表示字符串,0
表示数字,...)加上y
几乎总是等于y
代码>.添加该方法将使这两个工作都起作用:
顺便说一下,这是代码的更清晰版本:
:)
There is no way to define a
[]+=
method in ruby. What happens when you typeis
so both the
[]
and[]=
methods are called onx
(and+
is called onx[y]
, which in this case is anAutoHash
). I think that the best way to handle this problem would be to define a+
method onAutoHash
, which will just return it's argument. This will makeAutoHash.new[:x] += y
work for just about any type ofy
, because the "empty" version ofy.class
(''
for strings,0
for numbers, ...) plusy
will almost always equaly
.Adding that method will make both of these work:
And by the way, here is a cleaner version of your code:
:)
我认为你想要的是这样的:
hash = Hash.new { |h, k| h[k] = 0 }
hash['foo'] += 3
<代码># => 3
这将返回 3,然后是 6,等等,不会出现错误,因为新值默认分配为 0。
What I think you want is this:
hash = Hash.new { |h, k| h[k] = 0 }
hash['foo'] += 3
# => 3
That will return 3, then 6, etc. without an error, because the the new value is default assigned 0.