В 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 ответа

Решение

Другой вариант будет использовать замыкание:

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 работает на каждый звонок.

Расширение FunctionXX - это еще один способ достижения цели; это может иметь преимущество в предоставлении лучшей документации. Оба типа параметра и тип возвращаемого значения видны в первой строке объявления:

val activeUser = new Function0[List[String]] {
  val users = getUsersFromDB
  def apply = users filter (_.active)
}
Другие вопросы по тегам