2017-07-15 72 views
2

我正在使用抽象語法樹,其中每個頂點都是Node類的子類。這個基類在第三方庫中定義,並且對象在施工時被凍結。凍結對象中的記憶方法

現在我正在執行一些遍歷樹的昂貴的操作,有時是遞歸的,並且想記憶這些操作的結果。下面是這樣一個子類,和運算結果的一個例子使用「經典」紅寶石圖案被memoized:

class DefNode < Node 
    def visibility_scope 
    @visibility_scope ||= VisibilityScopeResolver.new(self).resolve 
    end 
end 

然而,由於Node構造凍結對象嘗試分配給一個實例變量導致錯誤:

DefNode.new(children).visibility_scope 
#=> RuntimeError: can't modify frozen DefNode 

有沒有一種方法(自然)執行memoization凍結對象?理想情況下,不要覆蓋每個子類中的構造函數。

回答

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=,因此不會與手動定義的閱讀器發生衝突。然而,我選擇了一個明確的名字,以儘量減少混淆的可能性。

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