r-lib / later

Schedule an R function or formula to run after a specified period of time.
https://r-lib.github.io/later
Other
137 stars 27 forks source link

`break`/exit recursive later? #169

Closed dereckmezquita closed 1 year ago

dereckmezquita commented 1 year ago

Hello,

I want to use later as a sort of setInterval equivalent from JavaScript.

I’d like to be able to break the loop”” under certain conditions. I came up with the following but it throws an error that there is no for loop to break out of which makes sense; etc so it doesn’t work.

I also tried returning NULL or using stop() which didn’t work either.

How can I break out of a recursive loop like this?

I want to use later as it allows me the most precise time control from all the methods, and infinite repetitions. I will be using it to write a script to get some data from an exchange and run some algorithmic trading.

I am aware most would write a trading bot in C++ rather, which I can do - I am using Rcpp - but that is not the point I’d like to accomplish something like this using R.

Here is the test code I have:

counter <- 1
exit_programme <- FALSE

main_programme <- function(interval = 5) {
    utils::timestamp()
    later::later(main_programme, interval)

    ## ------------------------------------
    counter <<- 1 + counter
    print(counter)
    if (counter > 5) break;
    if (exit_programme) break;
}

main_programme()
wch commented 1 year ago

All you need to do is make the later::later() call conditional. That function is the one that schedules the main_programme function to run again, so when you want to stop, just make sure not to call it.

Remember that you are scheduling this function to be called every few seconds. You can exit the function early with return(). This is essentially the same as what you would do in JavaScript with setTimeout (not setInterval).

I modified your script to do this:

counter <- 1
exit_programme <- FALSE

main_programme <- function(interval = 5) {
    utils::timestamp()

    counter <<- 1 + counter
    print(counter)
    if (counter > 5) { 
      exit_programme <<- TRUE
    }
    if (exit_programme) {
      return()
    }

    later::later(main_programme, interval)
}

main_programme()
#> ##------ Mon Nov 21 17:47:59 2022 ------##
#> [1] 2
#> ##------ Mon Nov 21 17:48:00 2022 ------##
#> [1] 3
#> ##------ Mon Nov 21 17:48:01 2022 ------##
#> [1] 4
#> ##------ Mon Nov 21 17:48:02 2022 ------##
#> [1] 5
#> ##------ Mon Nov 21 17:48:03 2022 ------##
#> [1] 6
dereckmezquita commented 1 year ago

Wonderful thank you very much @wch you know it seems so obvious when I see it.

I’m a fan of your work by the way with R6 etc please keep it up!

Last question please if you don’t mind; any update on promises/futures - I saw it mentioned in the readme for later it would be a wonderful addition to the toolkit.