I've a package that uses many checker functions (that use rlang::abort()
under the hood) to display the name of the caller function in error messages.
Although I try to abort as soon as possible, some of these checker functions are nested more or less deeply in various R6 methods. For example, public methods that rely on a base private method that uses another method to process some data that wraps another method to perform data type check, sometimes with intermediate helper functions using map()
or walk()
.
Currently, I'm relying on the following function as the default argument in abort()
to bubble up to the user environment and retrieve the right function call:
function() {
caller_env(sys.parent())
}
That works in some cases, fails in others (in particular when used inside walk()
/map()
functions), but it's relatively unreliable in general.
I'd like to improve that aspect to ensure error messages always show the right call.
The obvious solution is to pass calling environments along every function but that's quite messy in my case due to the number of functions/methods to change and feel somewhat unnatural to add this type of parameter in some functions.
Another solution (that I don't like) would be to give a fix number to retrieve the calling environment from deeper in the frame stack so that I don't have to add a new parameter to lots of functions. This is very fragile though.
I could also check arguments in all public methods directly but that's also fragile when using a common helper in various places because it easy to forget some checks.
Are there better alternatives?