Liftweb - Многократное изменение состояния ValueCell - PullRequest
2 голосов
/ 20 января 2012

В моем приложении я использовал некоторые «данные» ValueCell (что-то вроде 20) и я хотел бы создать ValueCell, который будет использоваться для обнаружения, если какие-либо из моих «данных» ValueCell были обновлены. Поэтому я хотел бы, чтобы эта ячейка менялась всякий раз, когда меняются другие ячейки.

Вот простой пример кода

class StringFilter {

  val referenceList = "foo"::"bar"::"scala"::"lift"::Nil

  val length = ValueCell[Int](3)
  val content = ValueCell[String]("")

  //Here I put some functions to update length or prefix on my webpage
  def filter(s:String):Boolean = (s.length==length.get)&&(s.contains(content.get))

  val changed =ValueCell[???](???)
  val results= changed.lift(referenceList.filter)
}

Что я должен поставить вместо ???? Я также открыт для решений, которые не используют ValueCells, даже если в конечном итоге мне понадобятся некоторые ячейки, потому что я должен использовать WiringUI.

Редактировать: length и content не обязательно должны быть ячейками, но их нужно установить

Редактировать: После дополнительных исследований я пришел к мысли: реализовать case class, как SeqCell, но который бы не принимал тип для Ячеек в параметре и для произвольного числа ячеек , Возможно ли это?
Вот реализация SeqCell:

final case class SeqCell[T](cells: Cell[T]*) extends Cell[Seq[T]] {

  cells.foreach(_.addDependent(this))

  /**
  * The cell's value and most recent change time
  */
  def currentValue: (Seq[T], Long) = {
    val tcv = cells.map(_.currentValue)
    tcv.map(_._1) -> tcv.foldLeft(0L)((max, c) => if (max > c._2) max else c._2)
  }

  /**
   * If the predicate cell changes, the Dependent will be notified
   */
  def predicateChanged(which: Cell[_]): Unit = notifyDependents()
}

Редактировать: В Scala Cell не является ковариантным , поэтому мне кажется, что я не смогу сделать SeqCell из своих ячеек с несколькими типами. Я был бы очень признателен за глобальное решение для произвольного числа ячеек.

1 Ответ

1 голос
/ 20 января 2012

Выезд FuncCell . Это просто еще одна ячейка, которая будет определять ее значение в зависимости от одной или нескольких других ячеек. Ссылка, которую я дал, является сопутствующим объектом, который имеет методы применения для 1-5 ячеек, соответствующих существующим реализациям FuncCell1 .. FuncCell5. Когда одна из этих ячеек изменит значение, FuncCell обновит свое собственное значение - тогда вы подключите WiringUI к вашему FuncCell.

Пожалуйста, простите за любые синтаксические ошибки, у меня нет открытой IDE, чтобы проверить себя ...

val changed: Cell[List[String]] = FuncCell(length, content){(len,con) =>
  def filter(s: String) = (s.length == len) && (s.contains(con))
  referenceList.filter(filter _)
}

Если все верно, то changed теперь является Cell, значение которого будет отражать результат вызова referenceList.filter


В ответ на ваши изменения относительно SeqCell я могу придумать два решения:

1) Используйте Any в качестве параметра типа в SeqCell

val cell1: ValueCell[Int] = ...
val cell2: ValueCell[String] = ...
val cell3: ValueCell[Stuff] = ...
...
val combined: SeqCell[Any] = SeqCell(cell1, cell2, cell3, ...)
val results = FuncCell(combined){ seq: Seq[Any] => ... }

2) Объедините промежуточные ячейки в кортежи, чтобы вы могли использовать существующие реализации FuncCell.

val intermediate1: Cell[(Int,String)] = 
  FuncCell(cell1,cell2){(a:Int, b:String) => a -> b}
val results = 
  FuncCell(intermediate1, cell3){(i: (Int, String), s: Stuff) => ...}
...