Scala が遅延パラメーターを導入する理由。値がどのように初期化されるかは、JVM (ユーザーには見えない) によって管理されるべきではありませんか? コントロールを開発者の手に委ね、値を遅延として定義する価値がある現実世界のユースケースは何ですか?
4 に答える
一般的なシナリオの 1 つは、初期化に費用がかかるクラスが使用されるかどうかをクラスの作成者が知らないval
場合です。この場合、val
はオンデマンドで初期化されます。
もう 1 つのシナリオは、初期化のシーケンスを有機的に制御することです。val
他のクラスがまだ初期化されていないため、特定のオブジェクトが初期化されるずっと前にオブジェクトが作成されることがよくあります。この場合、遅延は、この順序付けが自然に発生する便利な方法を提供します。作成者は、複雑な多段階の初期化を順序付けするマスター プランを考え出す必要はありません。
TLDR:ユーザーを驚かせ、パフォーマンス上の理由から
今日の言語のほとんどはeagerです。それらのいくつかはそうではなく、怠け者と呼ばれています. 多くのプログラミングの問題は、遅延評価によって美しく簡潔に表現できますが、完全に遅延することは良い考えではないと思います。主観的な観点から言えば、プログラマーは熱心に考えることに慣れているので (特に命令型の土地から来た人は)、たとえば Haskell で素朴に書かれたプログラムはあなたを大いに混乱させるかもしれません。考えられるすべての料理にフォークしかないのは、フォークとスプーンのどちらかを選択できるほど良くありません。scala は言語レベルで遅延評価をサポートしていますが、デフォルトでは熱心なモデルになります。その理由は (Martin と他の言語設計者の個人的な選択に加えて) Java と Scala の間の相互運用性にあります。この 2 つの世界を 1 つの言語で構成するのは悪夢です。さらに、Scala 設計の時点では、JVM はまだそのような機能をサポートしていませんでした。多かれ少なかれパフォーマンスの高い遅延値は、Java 7 でメソッド ハンドルが導入されて初めて可能になりました (わずか 2 年前ですが、scala は 10 年前からありました)。
私は自分の質問に答えます。したがって、遅延値が非常に役立つ使用例の 1 つは、サイクルを使用して不変のデータ構造を作成する場合です。怠惰がなければ、すでに作成されているオブジェクトを変更する必要があるため、簡単なことではありません。オブジェクトを不変にしたい場合、これは不可能です。例として単純なサイクルの実装を使用しましょう。
したがって、Scala では、次の方法でこれを実装できます。
class Node(inNode: => Node) { lazy val in = inNode }
lazy val node :Node = new Node(new Node(node))
このようにして、不変のサイクルを作成しました。参照を比較することで結果を確認できます。
scala> node.in
res3: Node = Node@2d928643
scala> node.in.in
res4: Node = Node@3a5ed7a6
scala> node
res5: Node = Node@3a5ed7a6