我正在使用抽象语法树,其中每个顶点都是ggplot(mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(c("cyl", "drv"))
类的子类。此基类在第三方库中定义,Node
对象在构造时冻结。
现在我正在执行一些遍历树的昂贵操作,有时是递归的,并且想要记住那些结果。下面是这样一个子类的示例,并使用“经典”Ruby模式记忆操作结果:
Node
但是,由于class DefNode < Node
def visibility_scope
@visibility_scope ||= VisibilityScopeResolver.new(self).resolve
end
end
构造函数冻结了对象,因此尝试分配给实例变量会导致错误:
Node
有没有办法(特意)在冻结的对象中执行memoization?理想情况下,不要覆盖每个子类中的构造函数。
答案 0 :(得分:1)
我不确定“惯用语”,但是当我去过那里时,我在课堂上使用了哈希:
class DefNode < Node
def self.visibility_scopes
@visibility_scopes ||= {}
end
def visibility_scope
self.class.visibility_scopes[__id__] ||=
VisibilityScopeResolver.new(self).resolve
end
end
答案 1 :(得分:0)
我最终做的是声明一个private
编写器,它允许有条件地设置值,即使在冻结的对象中:
class DefNode < Node
def visibility_scope
resolved_visibility_scope ||= VisibilityScopeResolver.new(self).resolve
end
private
attr_writer :resolved_visibility_scope
end
我选择了这个解决方案,因为它允许状态包含在实例本身中,这更容易推理,并且不会产生任何无法预料的副作用。这样做的一个缺点是,乍一看,它看起来并不像熟悉的“玫瑰记忆”模式。
值得注意的是,编写者也可以命名为visibility_scope
,因为它只定义#visibility_scope=
,因此不会与手动定义的读者冲突。然而,我选择给它一个不同的名称,以尽量减少混淆的可能性。