If I create an object that has a memowised value, then .dup to clone that object, the resulting duped object seems to share the same cache entry as the original object. Then these two objects have some sort of invisible coupling.
Example:
require "memo_wise"
class MyTest
prepend MemoWise
def initialize(value)
@value = value
end
attr_reader :value
def computed_value = 2 * @value
memo_wise :computed_value
def increment
@value += 1
reset_memo_wise
end
end
original = MyTest.new(5)
puts original.value # Outputs 5
puts original.computed_value # Outputs 10
duped = original.dup
puts duped.value # Outputs 5
puts duped.computed_value # Outputs 10
# should just reset duped's memowise cache, but resets both
duped.increment
# calling computed_value on duped will update the cached computed_value for both objects
puts duped.value # Outputs 6
puts duped.computed_value # Outputs 12
puts original.value # Outputs 5
puts original.computed_value # X - Outputs 12 instead of 10
Similar example, in reverse order
require "memo_wise"
class MyTest
prepend MemoWise
def initialize(value)
@value = value
end
attr_reader :value
def computed_value = 2 * @value
memo_wise :computed_value
def increment
@value += 1
reset_memo_wise
end
end
original = MyTest.new(5)
puts original.value # Outputs 5
puts original.computed_value # Outputs 10
duped = original.dup
puts duped.value # Outputs 5
puts duped.computed_value # Outputs 10
# should just reset duped's memowise cache, but resets both
duped.increment
# calling computed_value on original will update the cached computed_value for both objects
puts original.value # Outputs 5
puts original.computed_value # Outputs 10
puts duped.value # Outputs 6
puts duped.computed_value # X - Outputs 10 instead of 12
Example with mutable cached value
Here, duped keeps the same exact object instance cached for computed_value, so modifications done to either will be visible in both.
I would have expected that duped's memowise cache would start empty, and allow it to build its own computed_value.
require "memo_wise"
class MyTest
prepend MemoWise
def initialize(value)
@value = value
end
attr_reader :value
def computed_value = { "value" => @value }
memo_wise :computed_value
end
original = MyTest.new(5)
puts original.value # Outputs 5
puts original.computed_value # Outputs {"value"=>5}
duped = original.dup
puts duped.value # Outputs 5
puts duped.computed_value # Outputs {"value"=>5}
duped.computed_value["value"] += 1
puts duped.value # Outputs 5
puts duped.computed_value # Outputs {"value"=>6}
puts original.value # Outputs 5
puts original.computed_value # X - Outputs {"value"=>6} instead of {"value"=>5}
puts duped.computed_value.object_id == original.computed_value.object_id # Outputs true which is IMO unexpected
Tested with 1.13.0
If I create an object that has a memowised value, then
.dupto clone that object, the resulting duped object seems to share the same cache entry as the original object. Then these two objects have some sort of invisible coupling.Example:
Similar example, in reverse order
Example with mutable cached value
Here,
dupedkeeps the same exact object instance cached for computed_value, so modifications done to either will be visible in both.I would have expected that
duped's memowise cache would start empty, and allow it to build its own computed_value.Tested with 1.13.0