我有一個使用更大的索引在過程中創建大型數據結構的scala過程。因爲我想要一次完成並且不會在複雜的優先解決方案中變得難以理解,所以在使用表達式初始化的結果中使用lazy vals,該表達式可能無法在創建時評估爲正確值(或者任何其他值)該組件,但是一旦整個構建過程完成,就會這樣做。這意味着最終結果的每個組成部分都有對整個索引的閉包的合成引用,並且可能只要它們中的任何一個仍在內存中,我的索引就不能被垃圾收集。很顯然,我不想要它 - 理想情況下,我希望能夠在結構上進行第二遍以便根據需要初始化值(並確保在此處捕獲任何錯誤),並讓索引爲垃圾收集。目前,我通過名字初始化表達式通過幾個功能和懶惰VAL聲明中使用它,等價於:Scala:懶惰的vals,按名稱調用,關閉和內存泄漏
class Component(init : =>Component) {
lazy val property = init
}
...
new Component(index.get(parameters))
是這種聲音?將通過取消引用一次lazy val訪問的合成init字段?如果我想在初始化函數中使用它,就像這樣:
class Component(init : =>Component) {
private def evaluate = init
lazy val property = evaluate
}
有沒有什麼規則與封閉編程時保持在一般的想法?
你能稍微加重一點真實的代碼嗎?如果'index.get'已經是一個返回一個'Component'的函數,那麼這個包的好處是什麼?此外,哪些類型是可變的(有些必須是,否則沒有初始化順序問題) – Martijn
真正的代碼是相當龐大的,但底層的問題是非常基本的:合成閉包垃圾收集後,懶惰的val初始化,如果它只用於該初始化(特殊情況),並有任何規則管理它(通用之一)。在我的情況下,唯一的可變結構是在構建過程中使用的索引,所有其他正向/循環引用都是通過用表達式返回正確值的表達式來初始化的惰性val解析的。閉包的存在是因爲初始化表達式可能比較複雜,並且有關於哪些元素不應該關心的論點 – Turin
它不一定是真正的代碼 - 甚至是任何真正的代碼,只是足夠自成一體編譯並顯示有問題的行爲的例子 – Martijn