0

I have started playing with Bacon.js, and I have come across a problem I can't find any example for.

I have a set of nodes, which may reference other nodes.

It looks like this in imperative code:

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"

Now, I would like to have a Property for alice.likes.name, which has to change whenever alice.likes points to a different object, or the name property of the current object in alice.likes changes.

I have come up with the code below (LiveScript syntax), which correctly logs 3 messages: Bob, Bobby, Carol.

I'm using Bus for testing purposes.

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)

Question: How can I make a Property that represents the name of alice.likes.name?

I.e:

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

I'm new to FRP, so let me know if I'm doing something horribly wrong.

Leventix
  • 3,789
  • 1
  • 32
  • 41
  • 1
    Changing the names of people is odd. But other than that, have a look at `flatMap` – Bergi Sep 19 '15 at 16:11
  • Your solution with `flatMapLatest` is fine. What I would recommend is rethinking how you model the world: your example is object oriented thinking, entities that change their state == mutable data. Could you remodel your problem so that data is just data and is never mutated. Obviously you are not really working with people and their names, so it's hard to give more concrete advice. – OlliM Sep 20 '15 at 08:51
  • @OlliM I'm experimenting with creating a visual / projectional programming tool. There are nodes that represent programming elements, e.g. a variable, expression, etc. A variable can have a name, and multiple expressions can reference a variable. If I change the name of the variable, I want its name to be changed in every place a reference to it is shown. Also, if I change the reference to another variable, it should show the name of the new one. Can you give a bit more clue on how would I go without mutating data? I would like to avoid copying the whole graph on every interaction. – Leventix Sep 21 '15 at 07:38

1 Answers1

0

Thanks @Bergi for pointing me to flatMap.

flatMap creates a new stream for every event in the source. I used flatMapLatest, so that only the name changes from the latest liked person are transmitted on the output stream.

Here's the code:

nameOfAlicesFavourite = alice.pLikes.flatMapLatest (person) ->
  if person
    person.pName
  else
    Bacon.never!
Leventix
  • 3,789
  • 1
  • 32
  • 41