How to run code defined in a function in global scope?

Let's say I have a list of filenames and I want to write a function to, for each filename, import the file and clean it. This is a natural use of lapply, along the lines of

function cleaning_function = function(filename){
    df = read_csv(filename)
    df = df %>% rename(id = old_id)
}

list_of_dfs = lapply(filenames, cleaning_function)

The problem is debugging. Let's say the column old_id did not exist in the csv file. My code will error.

But it's hard to debug the code now that it's in a function.

What are my options for working with this?

in Julia, you can wrap all your code inside the function in an @eval block

function cleaning_function(filename)
    @eval begin 
         df = read_csv(filename)
         df = df %>% rename(id = old_id)
     end
end

now df appears in global scope and i can see what's going on when I get an error.

Is there any way to do the equivalent in R, an easy way to run commands in global scope for the purposes of inspecting intermediate variables?

If the goal is to inspect the objects in the case of an error, you can set options(error = recover). In the event of an error, this setting allows you to choose a frame of the call stack to enter using the symbolic debugger.

Very nice! I will try this.

Is there a way to do this without changing the error options? Something like enter() in the function definition?

All of the debugging tools i get when i search debugging in R seem overkill for my need, which is really just to enter the scope of a function.

There are lots of options for debugging a function. I briefly explain a few below. For more information check out the chapter Debugging in Advanced R by Hadley Wickham. For a higher-level introduction to debugging techniques, check out Jenny Bryan's talk from rstudio::conf 2020 Object of type ‘closure’ is not subsettable.

debug()

If you run debug(cleaning_function), you will be entered into the function environment to interactively debug the next time the function cleaning_function() is executed. You can stop it by running undebug(cleaning_function) (or restarting your R session). The alternative debugonce() is similar, but it will only enter the debugger the first time the function is called.

browser()

You can stick browser() anywhere in the function to enter the debugger, e.g. the code below will enter you into the debugger whenever df doesn't have a column named old_id:

cleaning_function = function(filename){
    df = read_csv(filename)
    if (!"old_id" %in% colnames(df)) browser()
    df = df %>% rename(id = old_id)
}
2 Likes

browser is exactly what I want! thank you!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.