Giter Club home page Giter Club logo

Comments (14)

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024 1

@nordfjord thanks for the help, definitely learned something new.

from flyd.

StreetStrider avatar StreetStrider commented on August 15, 2024

@EmirGluhbegovic hello. I think it is drop repeats. Also, feel free to visit gitter chat.

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

@StreetStrider Is absolutely correct, we have the droprepeats module precisely for this usecase.

An example usage would be something along these lines.

import { dropRepeats } from 'flyd/module/droprepeats'
import { stream } from 'flyd'

const s = stream()
const result = [];

s.pipe(dropRepeats).map(val => result.push(val));

s(1)(1)(1)(2)(2)(3)

result // [1, 2, 3]

The module also exposes dropRepeatsWith with which you can supply your own comparator.

e.g.

import { dropRepeatsWith } from 'flyd/module/droprepeats'
import { equals } from 'ramda'
import { stream } from 'flyd'

const dropRepatsWithEquals = dropRepeatsWith (equals)

const s = stream()
const result = []

s.pipe(dropRepeatsWithEquals).map(val => result.push(val))

s({a: 1})({a: 1})({a: 2})

result // [{a: 1}, {a: 2}]

from flyd.

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024

@nordfjord @StreetStrider Thanks for the replies.

The issue I am having is that on a certain model state I fire off an action which updates the model state, the issue being that that causes the "StateChangeListener" to fire off again which then since the state is the same causes the same action to fire off again and so the loop continues ....

I would want the "StateChangeListener" to be able to compare the previous states state for a certain object value the the new states certain object value and if they differ then run the update action.

Looking at dropRepeat, looks like it will still be stuck in the loop. As the action will fire off which causes the listener to trigger the action etc...

from flyd.

StreetStrider avatar StreetStrider commented on August 15, 2024

@EmirGluhbegovic isn't that custom comparator would suffice for you? Or you need a full historical depth of your state to look in?

from flyd.

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024

@StreetStrider Thanks for getting back so quick.

I only need to compare the most recent state to the previous state.
The part I am a little confused with, (so maybe its my lack of knowledge of Flyd and streams in general), is that there might be different things I want to compare, using the above example would be tricky to implement for different types of "state change listeners" as each needs to compare a different part of the state. I assume the easier way would be in each actual listener to have the comparison done there of prevState vs currentState and then trigger the potential action.

Let me know if more concrete examples would help, (i.e if the above makes any sense :p)

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

@EmirGluhbegovic Would you be willing to provide a small example we could play with? I'm not sure I'm following what you need.

as for

there might be different things I want to compare

I would think ramda could help you

import { dropRepeatsWith } from 'flyd/module/droprepeats'
import { pathEq } from 'ramda'

dropRepeatsWith(pathEq(['some', 'deeply', 'nested', 'prop']))

But a small example, perhaps a jsbin would be lovely so we can better understand the problem.

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

You could perhaps use https://flems.io/#0=N4IgZglgNgpgziAXAbVAOwIYFsZJAOgAsAXLKEAGhAGMB7NYmBvAHhLID4AdNAAl7YwMAE259+AuNQBOEAA7FecadQC8XECWJy4iAPR6ArmjkBrAOb46WPWCgBPYbYfD8AKzgaOLPVNkKxCUkZeUVlNQ0tHX0jEwsrWhtpbGEMLx8-UMCBPUIhUR5+FgAjWmF7bP5CnNLysR92KA5KEDgYWGpiCHoERBAANkQAFhAAXwp0bFw+9wQqOgYmYjwFuDDiDEZeVV47R3w16SEsAAoASgBuFraOrp68AAZEACYADjGJkEwcPCs4OZo9EYzD6YwAuqMgA

As a baseline

from flyd.

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024

@nordfjord @StreetStrider I have added an example. Please let me know if that makes sense.
I added the example here:
view example here

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

I see, Looking at the code the big problem seems to be the updateRoute method.

It's mutating the navigation object.

meaning any comparison is futile at that point.

function updateRoute() {
  update(R.assocPath(['navigation', 'path'], 'test'));
}

Is equivalent barring the mutation.

If we then add dropRepeatsWith to the mix we can create a function eqPath

const eqPath = R.curry(function(p, v1, v2) {
  const getPath = R.path(p);
  return R.equals(getPath(v1), getPath(v2));
});

With that function we can use dropRepeatsWith on the state stream

models
  .pipe(dropRepeatsWith(eqPath(['navigation', 'path'])))
  .map(routeSubscriber);

Here's the link

from flyd.

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024

I see it works correctly, but I don't fully understand some of the code. Also what the is R object? Is that reference to Ramda?

If you can run me through the logic that would be very helpful.

Thank you

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

The most important part was changing the updateRoute function

for an example why the old version was problematic, let's take a look at this:

const state = {route: ''};
const results = [state];
function test() {
  state.route = 'test';
  results.push(state);
}

test();
results; // [{route: 'test'}, {route: 'test'}]

This means any comparison is moot because of the mutation.

So to fix this we use R.assocPath (R is the reference to the ramda object)

assocPath associates a value to a given path immutably.

R.assocPath(['route'], 'test', {}) // {route: 'test'}

The example above would then yield

const state = {route: ''};
const results = [state];
function test() {
  results.push(R.assocPath(['route'], 'test', state));
}

test();
results; // [{route: ''}, {route: 'test'}]

Now as for the dropRepeats, we needed a function that could compare a value inside a nested structure.

const eqPath = R.curry(function (p, v1, v2) {
  const getPath = R.path(p); // getPath takes an object and returns the value at path p
  return R.equals(getPath(v1), getPath(v2)); // compare the values at path p in both objects 
});

We can then use eqPath with dropRepeatsWith to drop sequential equal values

model
  .pipe(dropRepeatsWith(eqPath(['navigation', 'state'])))
  .map(routeSubscriber)

from flyd.

EmirGluhbegovic avatar EmirGluhbegovic commented on August 15, 2024

@nordfjord Thank you, appreciate you taking your time to explain this.

I want to ask with regards to the curry function, are you using it so that, you automatically are giving it the first parameter with "eqPath(['navigation', 'state'])", then the first time it gets called the "v1" parameter will get called and the second time it gets called the function will have all 3 parameters and therefore run?

If that is the case does that mean then that every subsequent call then fills in the v1 field again and the following the v2 field? Havn't used Ramda or curry type functions, read the docs on ramda.

Want to understand what is exactly happening the background there with the curry function as that part of the eqPath function seems to be the key to the rest of the logic.

from flyd.

nordfjord avatar nordfjord commented on August 15, 2024

Curry allows you to call the function with any number of parameters, if they are too few then a function is returned which takes the rest of the arguments.

e.g.

const add = R.curry((a,b)=> a + b);

const add1 = add(1) // (b) => 1 + b

add1(2) // 3;

In our case we have eqPath

const eqState = eqPath(['navigation', 'state']) // (v1, v2)=> boolean

eqState({}, {}) // true

const eqStateTest = eqState({navigation: {state: 'test'}}) // (v2)=> boolean

eqStateTest({navigation: {}}) // false
eqStateTest({navigation: {state: 'test'}}) // true

from flyd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.