5

私は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 

:()そのリストを呼び出します私がここで紛失しているものだけが不思議です。

+0

あなたは正しいと思います。私はあなたが "機能的な感触"が複数のスレッドで使用されている場合には壊れていると言うことができると思います。機能プログラムはシームレスに並んでいるはずですか?知りません。 – Owen

答えて

3

正しいですか:機能的なコードは、実装の一部として内部状態を使用する場合、複数のスレッドによって使用される場合、非機能的にレンダリングされる可能性があります。これを修正するには、可変変数に接触するすべてのメソッド(つまりブロック​​)を同期させます。残念ながら、これはパフォーマンスにとって理想的ではありません。なぜなら、スレッド化されたアプリケーションでは、機能実装がしばしば好まれるからです。

+0

さてさて、私は狂っていないことを確認したかった。これらの定義に少し曖昧さがあるかもしれないという譲歩、あるいは少なくともそれらが意味するものについての完全な合意ではないかもしれません...作者のように実際にこの「純粋に機能的」または「不変」と呼ぶのは公正でしょうか?適切な条件の下で機能的に見えますが、確かに不変ではありません...私はそれが状態をかなり明確に変更し、機能的な外観が複数のスレッドで分解されることを意味します。私は作者の執筆を考えており、巨大なツールのように見えたくないので尋ねます。 –

+0

@Chris K - 私はそれを不変と呼ぶのは公正だと思いますが、スレッドの安全性について警告することも賢明です。コンピュータは本質的に変更可能なデバイスです。ほとんどの場合、操作が不変に見えるように設計されていても、操作の原因になるか、そうでなければ失敗するようにする方法があります。問題は実際にあなたが状態を突然変異させるために設計されたインターフェースを提供しているのか、それがどれほど脆弱であるのかということです。マルチスレッド化がそれほど珍しいわけではないことを考えると、この脆弱性は残念ですが、「純粋に機能的ではない」ということが正確であるとは確信していません。 –

関連する問題