Input checking for user-defined functions
somewhere (in a future PR) we need to check that these are actually functions, now that we take them from the user
Originally posted by @sbfnk in https://github.com/epiforecasts/ringbp/pull/84#discussion_r2058884235
@sbfnk, @pearsonca do you have a preference on using another package to do the input checking versus base R? In Epiverse we use {checkmate} which is a lightweight package and works well, it also seems to be used in other epiforecasts packages (e.g. {EpiNow2}).
{checkmate} sounds good to me
For error checking: if the plan is to go to mini argument collections, ala community_opts, isolated_opts, etc - probably do that first? Those will have their own error checking constructors, and then the functions that consume those can do is-a-class style checking, and you can keep implementation low clutter.
Also, it seems like when you add the checking, you'll either need to 1) trim the API, 2) refactor to have internal, unchecked versions of some functions, 3) have some unchecked functions, or 4) eat performance hit of checking every outbreak_step (possibly others, but that's a problem off the top of my head).
My recommendation is 1).
For error checking: if the plan is to go to mini argument collections, ala community_opts, isolated_opts, etc - probably do that first? Those will have their own error checking constructors, and then the functions that consume those can do is-a-class style checking, and you can keep implementation low clutter.
I will add some simple input checking in the feature branch I'm working on now, which does not include the refactor to use argument groupings (#65). Then I will follow this up with the refactor of the function signatures where I will finalise and refine the input checking.
My recommendation is 1).
Yes, I agree. Will tackle in a separate PR to the input checking.
The check_dist_func() internal function was added in PR #127 to check user-defined functions are valid.
For error checking: if the plan is to go to mini argument collections, ala community_opts, isolated_opts, etc - probably do that first? Those will have their own error checking constructors, and then the functions that consume those can do is-a-class style checking, and you can keep implementation low clutter.
The delay_opts(), event_prob_opts(), intervention_opts(), offspring_opts(), and sim_opts() function have been added in PR #127 which contain input checking of arguments, and return a specific S3 class attribute which is checked in scenario_sim(), outbreak_model(), outbreak_setup() and outbreak_step().