在Scala中,如何在函数内声明静态数据?

时间:2009-10-04 10:13:08

标签: 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相关的轻微语法怪异。

  • 在语言层面是否支持此类内容?
  • 如果没有,您在这种情况下使用的标准技术是什么?

2 个答案:

答案 0 :(得分:35)

另一种选择是使用闭包:

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

说明

activeUsersFunction1[Unit, ...your filter result type...]类型的变量(或者我们可以将此类型写为(Unit => ...your filter result type...),它是相同的),即此变量存储函数。因此,您可以稍后以与功能无法区分的方式使用它,例如activeUsers()

我们用一个代码块初始化这个变量,我们声明变量users并在匿名函数() => users.filter(_.active)中使用它,因此它是一个闭包(因为它有一个绑定变量{{1} })。

因此,我们实现了您的目标:(1)users看起来像一个方法; (2)activeUsers计算一次; (3)users适用于每次通话。

答案 1 :(得分:6)

扩展FunctionXX是实现目标的另一种方式;它可能具有提供更好文档的优势。参数类型和返回值类型都在声明的第一行可见:

val activeUser = new Function0[List[String]] {
  val users = getUsersFromDB
  def apply = users filter (_.active)
}