简体   繁体   中英

How to update values from an inner scope with a functional approach?

I have a case where I get an array of two strings from a client, and I map over them opening a stream for each of them, on the server side. (In the code example, I'm using a setInterval instead of the real data stream to keep things as simple as possible.)

I also restructure this data in an object, so I can keep values which I'll update later. Whenever setInterval is triggered, I increment the value of the key which is corresponding to the iteratee I'm mapping on.

const stream = (arr) => {

    // arr = ['firstValue', 'secondValue']

    // the object to store the values which will be sent to the client
    const restructure = {
        [arr[0]]: 0,
        [arr[1]]: 0
    }

    arr.map((i) => {
        // setInterval as a placeholder stream
        setInterval(() => {
            restructure[i]++
            // instead of logging, the updated object is sent to client
            console.log(restructure)
        }, 2000)
    })
}

And after bumping up the value, I send the updated object back to the client. Obviously this works but I want to do this update operation with a more functional approach.

I've tried some methods from Ramda and Lodash/Fp but it seems like it's impossible update the object from different scopes.

Usually what ends up happening is the values get bumped and then they go back to their original value on the next interval.

Is there a viable way of updating this data from the inner scope via a some sort of functional setState ?

Ramda is very much designed on the principle of never modifying user data. That doesn't mean that you can't do so using Ramda, but the Ramda functions themselves won't help you do it. This is quite intentional; immutable data structures are one of the important concepts of functional programming.

As to your example, the first thing I note is that your stream function doesn't return anything. Again, this is an odd thing in FP.

Now, as to using Ramda inside your function, you could, for instance start by using let restructure = fromPairs(map(key => [key, 0], arr)) .

And inside your setInterval you could reset that restructure value yourself, with something like restructure = evolve({[i]: R.inc}, restructure) .

Putting it all together, we could have something similar to your example with

const stream = (arr) => {
  let restructure = fromPairs(map(key => [key, 0], arr));
  R.map((key) => {
    setInterval(() => {
      restructure = evolve({[key]: R.inc}, restructure            
      console.log(restructure);
    }, 2000)
  }, arr)

  return () => restructure
}

Again, Ramda does not actually update that variable in place. But it certainly does not prevent you from reassigning it.

You can see a slight variation of this in the Ramda REPL .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM