Search code examples
rdotfiles

Modifying base::quit defaults


I would like to update my .Rprofile to modify base::quit. The normal behavior of q and quit is to prompt you to ask if you'd like to save your workspace. I would like to modify these functions so that they default to not saving my workspace,1 e.g., by modifying the functions as below:

q <- function(save = "no") {
    quit(save = save)
}
quit <- function(save = "no") {
    quit(save = save)
}

There's a problem here, however. (I'm a little new to R, so my description may not be perfectly accurate.) The functions q and quit are added to the global environment. As a result, if I call ls(), these functions will be included. Adding in the following code

environment(q) <- as.environment("package:base")

seems to add q to the base namespace. That is, I see the following:

# > q
# function(save = "no", ...)
# {
#     quit(save = save), ...)
# }
# <environment: base>

However, when I call ls(), q and quit both still appear, and if I call rm(list = ls()) then both q and quit revert to their original definitions in base.

What should I be doing to avoid this behavior? I would like q and quit to be modified so that they only appear when I call ls(name = "package:base").


1 There are a few reasons for this. I often run R from the command line to inspect data files in directories where I’d like to be able to count on every file being a data file, and so don't want any dotfiles cluttering the directory. Moreover, any analysis or cleaning I do in the console is not likely to be reproducible.


Solution

  • Try the following - it works at the prompt but not tested in a startup script:

    Create a new environment:

    > e = new.env()
    

    Create a quit function in that environment. Call base::quit to stop infinite loops:

    > assign("quit",function(){base::quit()},envir=e)
    

    at this point "quit" is still the base quit:

    > quit
    function (save = "default", status = 0, runLast = TRUE) 
    .Internal(quit(save, status, runLast))
    <bytecode: 0x55c7741932f8>
    <environment: namespace:base>
    

    So we attach the environment:

    > attach(e)
    The following object is masked from package:base:
    
        quit
    

    And now quit is our quit:

    > quit
    function(){base::quit()}
    

    The only thing in our workspace is e:

    > ls()
    [1] "e"
    

    But we can remove that:

    > rm(e)
    > ls()
    character(0)
    

    and still our quit is our quit:

    > quit
    function(){base::quit()}
    

    because its attached, there's still a reference to it somewhere. I think. Anyway, try it.