Управление ресурсами с помощью FRP в Scala RX

Я использую scala rx для приложения. У меня есть реактивная переменная, содержащая File (это файл PDF). Я использую библиотеку для вывода страниц из этого файла PDF на экран. Теперь библиотека PDF, которую я использую, дает мне объект (назовем его Doc), который я могу использовать для рендеринга отдельных страниц. Но чтобы отобразить страницу из объекта Doc, объект Doc должен быть открыт (таким образом, ресурс должен быть получен).

Прямо сейчас я загружаю файл PDF для каждой страницы, которую я отображаю заново (создавая новый объект Doc и закрывая его после рендеринга одной страницы). Это делает рендеринг страницы функциональным (данный файл и номер страницы возвращают изображение).

Есть ли способ цепляться к открытому ресурсу и закрывать его при изменении в FRP вообще и для scala rx в частности? Как можно было бы справиться с этой очень распространенной ситуацией?


person ziggystar    schedule 01.06.2014    source источник


Ответы (1)


Вы можете просто заключить объект Doc. Поэтому вместо рендеринга

def render(file: File, pageNumber: Int): Image =  // blah blah blah

изменить его на:

def open(file: File): (Int => Image) = {
  val doc = // call your library to read file
  (x: Int) => doc.getPage(x)
}

а затем передайте, что функция open возвращает любой сигнал изменения страницы, на который вы реагируете.

Редактировать: О, я вижу, вы говорите, что хотите, чтобы он закрывал файл всякий раз, когда сигнал file:File меняется на другой файл. В этом случае вы сможете сделать что-то вроде этого:

def pageGetterRx(file: Rx[File]): Rx[Int => Image] = {
  val doc: Var[Doc] = Var(null)
  val o = file.foreach { f =>
    Option(doc()).foreach(_.close)
    doc() = PdfLib.read(f)  // or however you do the reading
  }
  Rx {
    (x: Int) => doc().getPage(x)
  }
}

Редактировать 2: чтобы уточнить, если вы наложите на FRP различие «собрать сеть функций фазы / запустить сеть на фазе некоторого сигнала (ов), вышеуказанная функция будет вызываться только один раз; на этапе сборки. Другими словами, pageGetterRx (паршивое имя, я полностью осведомлен) не участвует в способе FR, вместо этого он возвращает сигнал лямбда-выражений, каждый из которых закрывает один конкретный файл и возвращает страницы из него.

person teryret    schedule 08.10.2014
comment
И как мне убедиться, что doc закрывается, когда он больше не используется? - person ziggystar; 08.10.2014
comment
Рука машет о сборщике мусора. ;-) Я имею в виду, что нет другого способа сделать это, если у вас нет другого сигнала, который сообщает вам, когда он больше не используется, и в этом случае вы можете просто заставить open возвращать две функции, по одной для каждого сигнала. - person teryret; 08.10.2014
comment
Вопрос конкретно в том, как освободить ресурс определенным образом. Извините, если это было не очевидно (я добавил ударение). - person ziggystar; 08.10.2014
comment
Если вы можете утверждать, что это невозможно, это также будет правильным ответом. - person ziggystar; 08.10.2014
comment
Извините, если это не идиоматично, я никогда не использовал scala rx, мой опыт работы с FRP связан с Elm. Но он должен получить представление о том, как это сделать... надеюсь? - person teryret; 08.10.2014
comment
Я думаю, что o получит сборщик мусора, но это можно исправить. Это решение в основном использует побочные эффекты. Я думаю, что вместо doc можно было бы использовать обычную переменную, поскольку локальное использование FRP, похоже, ничего вам не даст. - person ziggystar; 08.10.2014
comment
Мне было немного интересно, что насчёт o, вообще казалось странным называть его, но это то, что они сделали во вступительном руководстве scala rx, поэтому я придерживался этого. Закрытие файла является побочным эффектом, поэтому использование наблюдателя — правильный способ сделать это. То, что вы получаете от локального использования FRP, — это сигнал, позволяющий более поздним реактивным функциям знать, когда лямбда, получающая страницу, изменилась. - person teryret; 09.10.2014