ListBuffer
は効率的に要素を末尾に追加してからList
に変換できます。ScalaのListBufferクラスの+ =メソッドのソースコードに関する初心者のパズル
私はListBuffer
の追加メソッドのソースコード(+=
)を研究しましたが、その動作を理解することが難しいと感じました。詳細なソースコードはhereです。
抜粋ソースコード:else
一部で
final class ListBuffer[A] extends AbstractBuffer[A] {
private var start: List[A] = Nil
private var last0: ::[A] = _
private var exported: Boolean = false
private var len = 0
def += (x: A): this.type = {
if (exported) copy()
if (isEmpty) {
last0 = new :: (x, Nil)
start = last0
} else {
val last1 = last0 // last1 is a local variable, is it necessary here?
last0 = new :: (x, Nil)
last1.tl = last0 //
}
len += 1
this
}
}
、ローカル変数last1
が定義され、その後終了時にいくつかの要素を含むように構成されています。 last0
は常に最後のセルを指します。
ここにlast1
が必要ですか?結局のところ、それはブロックの後に範囲外になります。私はなぜ著者がlast1
をここで定義しなければならないのか理解できません。 last0
常に最後「のポイント」を行う必要があります。この減少に問題があります除き、ここで何が起こっている
ありがとうございました。まだ混乱している。なぜ "新しく作成された最後の要素を保持するために一時変数が必要"なのでしょうか? 'last0 = new ::(x、Nil)'は 'last0'のクラスフィールドに最後のセルを格納します。しかし、 'last1'は単なるローカル変数であり、' else'コードブロックの後に消えます。 – Spring
'last0'を動かすだけでは不十分です。今作成したばかりの要素を指すように、最後から2番目の要素の 'tl'も必要です。だから 'last0.tl = new ::(x、Nil); last0 = last0.tl'は 'last1'の代わりに' tl'を使ってうまくいくでしょう。 2つの間の選択は、味覚および/または性能試験の問題である。 – alf
この '+ ='メソッドの実装には問題があることがわかりました。追加された要素は 'start'リストに保存できませんでした。実行デモがあります:(1) 'val t = new ListBuffer [Int]'; (2) 't + = 1' // {' start = List(1) '、' last0 = List(1) '}; (3) 't + = 2 '; {'start = List(1)'、 'last0 = List(1)'}(4) 't.toList' {' List(1) '}です。 – Spring