私はOdersky、Spoon、VennersのProgramming In Scala第2版を使っています。この例題は関数型プログラミングについては真実だと思っていたので不変性。この例では(そしてCh.18の本の前半で)、作者はオブジェクトの操作がオブジェクトの状態を内部的に変更したとしても、依然として「純粋に機能的」であると主張しています。この例は、p.442、Ch。スカラ関数のプログラミングからの機能待ち行列
class Queue[+T] private (
private[this] var leading: List[T],
private[this] var trailing: List[T]
) {
private def mirror() =
if (leading.isEmpty) {
while (!trailing.isEmpty) {
leading = trailing.head :: leading
trailing = trailing.tail
}
}
def head: T = {
mirror()
leading.head
}
def tail: Queue[T] = {
mirror()
new Queue(leading.tail, trailing)
}
def enqueue[U >: T](x: U) =
new Queue[U](leading, x :: trailing)
}
これは、副作用がクライアントには見えない限り、このようなものは機能的と考えることができるということです。私はそれを後にすることができると思う...私は厳密に言えば、それは機能を定義するものです。しかし、確かに(そして私はJVMのメモリモデルが何を保証しているのか分かりませんが)、このコードでは潜在的な問題はありませんか?例えば
、2つのスレッドがこのようになりますこのキュー、上の操作を実行している場合は、起動します。
Leading: Nil
Trailing: List(1,2,3,4)
それは一つのスレッドが鏡の中のこの時点になって頭を()を呼び出すことができることはできません()スケジュール解除される前には:
private def mirror() =
if (leading.isEmpty) {
while (!trailing.isEmpty) {
leading = trailing.head :: leading
> trailing = trailing.tail
}
}
た時点で、キューは次のようになります。
Leading: List(1)
Trailing: List(1,2,3,4)
そしてときに、第2のスレッドが(尾を呼び出して)最初はアクティブでないときに、これが返されます:
Leading: Nil
Trailing: List(1,2,3,4)
最初のスレッドの頭()の呼び出しが終了するのであれば、これはその後の尾の後に返されるのに対し私は確かなものと並行プログラミング本当に私はそれが多くの人々のためであると確信しているとして、私は、私のためmindbendingさのこの種で素晴らしいじゃない
Leading: List(2,3,4)
Trailing: Nil
:()そのリストを呼び出します私がここで紛失しているものだけが不思議です。
あなたは正しいと思います。私はあなたが "機能的な感触"が複数のスレッドで使用されている場合には壊れていると言うことができると思います。機能プログラムはシームレスに並んでいるはずですか?知りません。 – Owen