Scalaでは、関数内で静的データをどのように宣言しますか? 質問する

Scalaでは、関数内で静的データをどのように宣言しますか? 質問する

多くの場合、関数のスコープ内で長期間有効な値を作成する必要があり、このデータがクラス/オブジェクト スコープにある必要はないことがわかります。

例えば、

object Example {

   def activeUsers = {
       val users = getUsersFromDB  // Connects to the database and runs a query.
       users.filter(_.active)
   }
}

上記では、変数はusers正しいスコープ内にありますが、関数がactiveUsers呼び出されるたびにデータベース クエリが実行されます。

これを回避するには、変数をusers関数のスコープ外に移動します。

object Example {
   val users = getUsersFromDB  // Connects to the database and runs a query

   def activeUsers = {
       users.filter(_.active)
   }
}

しかし、これにより他の機能でも利用できるようになります。

あるいは、関数を囲む別のオブジェクトを作成することもできます。

object Example {

   object activeUsers {
       val users = getUsersFromDB  // Connects to the database and runs a query.

       def apply() = {
           users.filter(_.active)
       }
   }
}

しかし、これには、より多くの定型コード、別のオブジェクトの使用、および に関連する若干の構文の奇妙さが伴いますapply

  • 言語レベルでこのようなサポートはありますか?
  • そうでない場合、この状況で使用する標準的なテクニックはありますか?

ベストアンサー1

別のオプションとしては、クロージャを使用することです。

object Example {
   val activeUsers = {
       val users = getUsersFromDB
       () => users.filter(_.active)
   }
}

説明

activeUsersは型の変数ですFunction1[Unit, ...your filter result type...](または、この型を と書くこともできますが(Unit => ...your filter result type...)、同じです)。つまり、この変数には関数が格納されます。したがって、後で関数と区別がつかない方法で使用できます。activeUsers()

usersこの変数は、変数を宣言して匿名関数内で使用するコード ブロックで初期化されます() => users.filter(_.active)。したがって、これはクロージャです (バインドされた変数があるためusers)。

その結果、(1)activeUsersメソッドのように見える、(2)users一度だけ計算される、(3)filterすべての呼び出しで機能するという目標が達成されます。

おすすめ記事