moodymudskipper / flow

View and Browse Code Using Flow Diagrams
https://moodymudskipper.github.io/flow/
Other
395 stars 26 forks source link

Improved recursive function display #46

Closed smingerson closed 3 years ago

smingerson commented 3 years ago

Not to imply the current display is bad! First definition fails, second doesn't, although both manage to render the diagram. I think it would be very cool to be able to step through each recursion and see the primary node get its arguments updated, instead of terminating at the end of the first call. I have complete confidence you can figure that out 😁.

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  Recall(n = n - 1)
}

flow_run(recurse_until_zero())

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  recurse_until_zero(n = n - 1)
}
flow_run(recurse_until_zero(), browser = TRUE)
moodymudskipper commented 3 years ago

Good catch for Recall(), I realize flow_run() is broken in many respects... I opened this issue about it : https://github.com/moodymudskipper/flow/issues/43

Recall() can be added to the list of problematic functions.

I think I have a path to the fix but it might take a bit of time to implement right.

Your second request, to have the diagrams refresh on recursion, should be possible once I implement flow_debug() : https://github.com/moodymudskipper/flow/issues/42

flow_debug() and flow_debug_once() would be like debug() and debugonce() but with browsable diagrams.

But I don't think I can display the change of n in the primary node, I don't display the arguments there but the formals of the function, it would be a problem to display the values of the argument because some may be subject to non standard evaluation.

moodymudskipper commented 3 years ago

flow_run2 was implemented temporarily, it will replace flow_run once I'm completely happy with it.

It's much more robust and uses browser() instead of an adhoc browser, which caused a lot of issues. It goes through loops, and shows, which is the greatest improvement besides robustness.

refresh() must be used to view the updated diagram at the chosen step.

When Recall() is used a single diagram is used for all recursions, if Recall() is not used only the parent call is shown, not further recursive calls.

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  Recall(n = n - 1)
}

flow::flow_run2(recurse_until_zero())
#> [1] 0

image

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  recurse_until_zero(n = n - 1)
}
flow::flow_run2(recurse_until_zero())
#> [1] 0

image

moodymudskipper commented 3 years ago

It is now implemented in flow_run().

What is really cool and happened almost by accident is that for a recursive function using Recall() we keep the same diagram, and using the new option show_passes = TRUE we can see what all iterations went through.

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  Recall(n = n - 1)
}

flow_run(recurse_until_zero(), show_passes = TRUE)
#> [1] 0

image

recurse_until_zero <- function(n = 10) {
  if (n == 0) {
    return(n)
  }
  recurse_until_zero(n = n - 1)
}
flow_run(recurse_until_zero(), show_passes = TRUE)
#> [1] 0

image

github-actions[bot] commented 2 years ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue and link to this old issue if necessary.