question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handling Nested Computations under Branching Logic

See original GitHub issue

I hit an interesting problem that I’m gathering I’m just attacking wrong but I wanted to see what you think. This goes back to issues around trying to do conditionals with boolean statements that can run too many times without changing their results. Obviously breaking synchronicity is another option. But as you may remember I’d been creating Roots to handle disposal. I came across an issue there recently that I hadn’t noticed before, I’m gathering due to manual disposal getting queued up (ie it’s frozen like the rest).

Here is the simplest reproduction I have. You can understand why you wouldn’t expect data to be re-evaluated again after the ternary evaluates the other way. Thoughts?

https://codesandbox.io/s/objective-tdd-dif57

The issue is when the condition turned from true to false and value is set to undefined it still evaluates the nested child and fails to find a value with length.

EDIT I was wrong this even happens when you break synchronicity:

import S from "s-js";

S.root(() => {
  const trigger = S.data(false),
    data = S.data(null),
    cache = S.value(S.sample(trigger)),
    child = data => {
      S(() => console.log("nested", data().length));
      return "Hi";
    };
  S(() => cache(trigger()));
  const memo = S(() => (cache() ? child(data) : undefined));
  S(() => console.log("view", memo()));
  S.freeze(() => {
    trigger(true);
    data("name");
  });
  S.freeze(() => {
    trigger(false);
    data(undefined);
  });
});

This produces the same error.

EDIT 2 https://codesandbox.io/s/vigorous-cherry-vo79c shows an even simpler re-production using only a single condition and no freezing.

import S from "s-js";

S.root(() => {
  const data = S.data(null),
    cache = S.value(S.sample(() => !!data())),
    child = data => {
      S(() => console.log("nested", data().length));
      return "Hi";
    };
  S(() => cache(!!data()));
  const memo = S(() => (cache() ? child(data) : undefined));
  S(() => console.log("view", memo()));
  console.log("ON");
  data("name");
  console.log("OFF");
  data(undefined);
});


Is this just by design and we should expect these states to exist at the same time?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:13 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
adamhailecommented, Oct 5, 2019

Hey Ryan, slow response, even for me 😦. Start-up ended up not working out, now on some intense contracting work trying to build back. Such is life.

On your examples up above, if I follow what you’re trying to do, the issue is that cache changes one tick after data. Since the nested computation’s lifecycle follows cache, it runs one more tick than it should and sees the undefined value in data, causing the exception.

Your code is probably boiled out of a more complicated actual case that would explain what you’re after, so this might not apply, but my thought would have been to do the simple thing:

const data = S.data(null);
S(() => {
    if (data()) console.log("(not) nested (any more)", data().length));
});

I think the intent of cache and its setter was to be more performant (correct me if I have that wrong), but I think it likely went the other way. Fundamentally, something still needs to run every time value changes. Adding the plumbing of a value signal and a computation that sets it doesn’t change that, it just adds more plumbing. So maybe tell me more about what you’re after and I can comment.

I kept parity between subclocks and the main implementation for a while, but the stuff around lazy node construction broke that 😦. I’m mixed on whether lazy node construction is worth the complexity it added or not. At one point, it occurred to me that the initial case we were looking at – avoiding constructing unneeded computations in DOM components – would be largely eradicated just by making a single computation per component rather than per node, the way Surplus had been.

0reactions
visjcommented, Nov 8, 2019

I created some benchmarks between double ended queues and the current, simpler Queue version, and preliminary it looks as if it does hit performance quite a bit.

If track cannot be implemented without causing too much slowdown I agree with @adamhaile that Subclocks probably is a better way forward as it solves more cases than track.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Use branching logic in Microsoft Forms
In Microsoft Forms, you can add branching logic to a survey or quiz form so that it changes according to the responses to...
Read more >
Introduction and Overview of REDCap
REDCap was developed to help scientific research teams with intuitive and reusable tools to collect and disseminate project-specific research ...
Read more >
A Temporal Logic of Nested Calls and Returns * - UPenn CIS
In a structured computation, for every position, besides the global and ab- stract successors, there is also a natural notion of the caller...
Read more >
Basic conditional branching with if-then statements
To create a branch in our program, is to create an alternative sequence of commands that may be ignored, based on certain conditions...
Read more >
Avoiding deeply nested Swift code
... need to handle a much larger amount of states and permutations, which in turn might require us to branch our logic into...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found