The struct does not update the getter if it is nested in another struct

huangapple go评论96阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年5月26日 01:33:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76334923.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定