Как я могу создать Bacon.Property, представляющий свойство в ссылочном объекте?

Я начал играть с Bacon.js и столкнулся с проблемой, для которой не могу найти примера.

У меня есть набор узлов, которые могут ссылаться на другие узлы.

В императивном коде это выглядит так:

alice = { name: "Alice" }
bob   = { name: "Bob" }
carol = { name: "Carol" }

alice.likes = bob
bob.likes = carol
alice.likes.name //=> "Bob"

bob.name = "Bobby"
alice.likes.name //=> "Bobby"

alice.likes = carol
alice.likes.name //=> "Carol"

Теперь я хотел бы иметь свойство для alice.likes.name, которое должно изменяться всякий раз, когда alice.likes указывает на другой объект, или свойство name текущего объекта в alice.likes изменяется.

Я придумал код ниже (синтаксис LiveScript), который правильно регистрирует 3 сообщения: Боб, Бобби, Кэрол.

Я использую Bus для тестирования.

mkBus = (initialValue) ->
  bus = new Bacon.Bus()
  property = bus.toProperty(initialValue)
  property.push = (newValue) -> bus.push(newValue)
  property

alice = { pName: mkBus("Alice"), pLikes: mkBus(null) }
bob   = { pName: mkBus("Bob"),   pLikes: mkBus(null) }
carol = { pName: mkBus("Carol"), pLikes: mkBus(null) }

alice.pLikes.onValue (person) ->
  if person
    person.pName.onValue (vName) ->
      console.log vName

alice.pLikes.push(bob)
bob.pLikes.push(carol)

# Change name
bob.pName.push("Bobby")

# Change reference
alice.pLikes.push(carol)

Вопрос. Как создать свойство, представляющее имя alice.likes.name?

I.e:

nameOfAlicesFavourite.onValue (vName) ->
  console.log vName

Я новичок в FRP, поэтому дайте мне знать, если я делаю что-то ужасно неправильное.


person Leventix    schedule 19.09.2015    source источник
comment
Менять имена людей странно. Но кроме этого, взгляните на flatMap   -  person Bergi    schedule 19.09.2015
comment
Ваше решение с flatMapLatest в порядке. Я бы порекомендовал переосмыслить то, как вы моделируете мир: ваш пример — объектно-ориентированное мышление, сущности, которые меняют свое состояние == изменяемые данные. Не могли бы вы изменить свою проблему так, чтобы данные были просто данными и никогда не изменялись. Очевидно, вы не очень-то работаете с людьми и их именами, так что более конкретный совет дать сложно.   -  person OlliM    schedule 20.09.2015
comment
@OlliM Я экспериментирую с созданием инструмента визуального / проекционного программирования. Есть узлы, которые представляют элементы программирования, например. переменная, выражение и т. д. Переменная может иметь имя, и несколько выражений могут ссылаться на переменную. Если я изменю имя переменной, я хочу, чтобы ее имя менялось везде, где отображается ссылка на нее. Кроме того, если я изменю ссылку на другую переменную, она должна показать имя новой. Можете ли вы дать немного больше информации о том, как мне обойтись без мутации данных? Я хотел бы избежать копирования всего графика при каждом взаимодействии.   -  person Leventix    schedule 21.09.2015


Ответы (1)


Спасибо @Bergi за то, что указал мне на flatMap.

flatMap создает новый поток для каждого события в источнике. Я использовал flatMapLatest, чтобы в выходной поток передавались только изменения имени от последнего понравившегося человека.

Вот код:

nameOfAlicesFavourite = alice.pLikes.flatMapLatest (person) ->
  if person
    person.pName
  else
    Bacon.never!
person Leventix    schedule 19.09.2015