Reputation: 17767
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
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
Reputation: 13221
Another option would be using a closure:
object Example {
val activeUsers = {
val users = getUsersFromDB
() => users.filter(_.active)
}
}
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