HRJ
HRJ

Reputation: 17767

In Scala, how would you declare static data inside a function?

In many situations I find that I need to create long-living values inside a function's scope, and there is no need for this data to be at class/object scope.

For example,

object Example {

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

Above, the variable users is in the correct scope, but it will execute a database query everytime the function activeUsers is called.

To avoid this, I could move the variable users outside the function's scope:

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

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

But that makes it available to other functions as well.

Else, I could create a separate object to enclose the function:

object Example {

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

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

But this involves more boilerplate code, use of another object and slight syntax oddities related to apply.

Upvotes: 27

Views: 5388

Answers (2)

Walter Chang
Walter Chang

Reputation: 11596

Extending FunctionXX is another way of achieving the goal; it might have an advantage of providing better documentation. Both parameter types and return value type are visible on the first line of the declaration:

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

Upvotes: 6

Alexander Azarov
Alexander Azarov

Reputation: 13221

Another option would be using a closure:

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

Explanation

activeUsers is a variable of type Function1[Unit, ...your filter result type...] (or we can write this type as (Unit => ...your filter result type...), which is the same), that is this variable stores a function. Thus you may use it later in a way indistinguishable from function, like activeUsers()

We initialize this variable with a block of code where we declare variable users and use it inside an anonymous function () => users.filter(_.active), hence it is a closure (as it has a bound variable users).

As a result, we achieve your goals: (1) activeUsers looks like a method; (2) users is calculated once; and (3) filter works on every call.

Upvotes: 36

Related Questions