英文:
The struct does not update the getter if it is nested in another struct
问题
这里是复现问题的代码 - https://carc.in/#/r/f4dp
我有一个值计数器,它是一个简单的哈希表,包装在 Counter 结构体中。每当它更新时,我会增加 getter 值 total,用于缓存目的。
我还有一个 Tree 结构体,我需要管理一组计数器。它的排列方式类似 - 在哈希表内部,键是某个数值,键的值是 Counter。
问题是,如果我创建一个 Counter 实例并增加值,getter total 会正确更新,但如果通过 Tree 进行操作,getter 始终为零。
起初,我以为是 yield 和内联块的问题,但尝试不使用 yield 得到了完全相同的结果。
我应该在哪里寻找问题?
英文:
Here is the code that reproduces the problem - https://carc.in/#/r/f4dp
module CounterTree
struct Counter
getter table : Hash(UInt64, UInt64)
getter total : UInt64
def initialize
@table = Hash(UInt64, UInt64).new
@total = 0_u64
end
def increment : UInt64
insert(key = timestamp, value : UInt64 = 1)
end
def insert(key : UInt64, value : UInt64) : UInt64
if @table.has_key?(key)
@table[key] += value
else
@table[key] = value
end
increment_total(value)
value
end
private def increment_total(value : UInt64) : UInt64
@total += value
end
private def timestamp
Time.local.to_unix_ms.to_u64
end
end
struct Tree
getter branches = [] of Hash(UInt64, CounterTree::Counter)
getter branches_num : UInt32
def initialize(@branches_num = 9)
@branches = Array.new(@branches_num) do
Hash(UInt64, CounterTree::Counter).new
end
end
def increment(key : UInt64) : UInt64
with_counter(key) do
increment
end
end
private def with_counter(key : UInt64)
index = (key % @branches_num).to_u64
unless @branches[index][key]?
@branches[index][key] = Counter.new
end
with @branches[index][key] yield
end
end
end
# Total is updated
counter = CounterTree::Counter.new
counter.increment
counter.increment
counter.increment
pp counter
puts "---------"
# Total is not updated
tree = CounterTree::Tree.new
tree.increment 1234_u64
tree.increment 1234_u64
tree.increment 1234_u64
pp tree
I have a value counter that is a simple hash table wrapped in a Counter struct. I increment the getter value total each time it is updated for caching purposes.
I also have a Tree struct, which I need to manage groups of counters. It's arranged in a similar way - inside a hash table, where the key is some numeric value, and the value of the key is Counter.
The problem is that if I create a Counter instance and increment the value, the getter total is updated correctly, but if I do it through Tree, the getter is always zero.
At first I thought there was some problem with the yield and block inline, but trying to rewrite without yield gave exactly the same result.
Where should I look for the problem?
答案1
得分: 0
问题通过使用 class 而不是 struct 来解决,因为:
> 可变的结构体仍然被允许,但如果您希望避免下面描述的意外情况,请在编写涉及可变性的代码时要小心。
英文:
The problem is solved by using class instead of struct because:
> Mutable structs are still allowed, but you should be careful when writing code involving mutability if you want to avoid surprises that are described below.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论