Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Calling functions in R usually involves typing brackets. And since many of our actions in R involve calling a function, we will have to type a lot of brackets working with R. Often it would make our life a lot easier if we could omit the need to type brackets where convenient. We will do exactly that today.
Work in R faster with custom bracketless commands
A good starting example is, well, quitting R altogether. Usually, one may do:
quit()
Which will in turn likely get you and extra question regarding saving a workspace image. So you then finally type n
and are done with it. If you want to be a bit faster, you may do:
q("no")
Better, but still an awful lot of typing just to quit R
, especially when working in a terminal-like environment with multiple sessions.
Let us be a bit craftier and make
R
quit just by typing
To make a bracketless command, we will (mis)use the fact that typing an object name into R console and pressing enter will often invoke a print method specific for the class of that object.
All we have to do to create our very first bracketless command is to create a custom print method for a funky class made for this single purpose. Then we make an object of that class and type its name to the console:
qq <- structure("no", class = "quitter") print.quitter <- function(quitter) base::quit("no") # This will quit your session NOT saving a workspace image! qq
Switching debugging modes with ease
Quitting R
quickly is more useful then it may sound when using multiple sessions in a terminal environment, but we can use the above approach to create different useful shortcuts making our life much easier.
One example I use very frequently is to change the error
option, which governs how R
behaves when encountering non-catastrophic errors such as those generated by stop
, etc.
- I find setting the option to
options(error = utils::recover)
very useful for debugging and at the same time very annoying when undesired. - Typing
options(error = NULL)
to change it back is however even more annoying. Or is itoptions("error") = NULL
? Or maybe evenoptions(error) = NULL
?
In comes the gg
shortcut:
gg <- structure(FALSE, class = "debuggerclass") print.debuggerclass <- function(debugger) { if (!identical(getOption("error"), as.call(list(utils::recover)))) { options(error = recover) message(" * debugging is now ON - option error set to recover") } else { options(error = NULL) message(" * debugging is now OFF - option error set to NULL") } }
Now we switch between the options with ease:
# When in need of debugging gg ## * debugging is now ON - option error set to recover # The option is now set to recover getOption("error") ## (function () ## { ## if (.isMethodsDispatchOn()) { ## tState <- tracingState(FALSE) ## on.exit(tracingState(tState)) ## } ## calls <- sys.calls() ## from <- 0L ## n <- length(calls) ## if (identical(sys.function(n), recover)) ## n <- n - 1L ## for (i in rev(seq_len(n))) { ## calli <- calls[[i]] ## fname <- calli[[1L]] ## if (!is.na(match(deparse(fname)[1L], c("methods::.doTrace", ## ".doTrace")))) { ## from <- i - 1L ## break ## } ## } ## if (from == 0L) ## for (i in rev(seq_len(n))) { ## calli <- calls[[i]] ## fname <- calli[[1L]] ## if (!is.name(fname) || is.na(match(as.character(fname), ## c("recover", "stop", "Stop")))) { ## from <- i ## break ## } ## } ## if (from > 0L) { ## if (!interactive()) { ## try(dump.frames()) ## cat(gettext("recover called non-interactively; frames dumped, use debugger() to view\n")) ## return(NULL) ## } ## else if (identical(getOption("show.error.messages"), ## FALSE)) ## return(NULL) ## calls <- limitedLabels(calls[1L:from]) ## repeat { ## which <- menu(calls, title = "\nEnter a frame number, or 0 to exit ") ## if (which) ## eval(substitute(browser(skipCalls = skip), list(skip = 7 - ## which)), envir = sys.frame(which)) ## else break ## } ## } ## else cat(gettext("No suitable frames for recover()\n")) ## })() # When done debugging gg ## * debugging is now OFF - option error set to NULL # The option is now back to NULL getOption("error") ## NULL
Making it practical (and a bit less barbaric)
Defining all the shortcuts in the way shown above every time is both tedious and ugly, making a mess in our global environment. We can therefore decrease the tedium and ugliness by:
- Adding the definitions into our
.Rprofile
with a proper notice, which will run the definitions and make the shortcuts available every time we start R standardly - Enclosing the definitions into a separate environment attached to the search path, potentially with a command to detach it easily
Such an .Rprofile
can look similar to:
message("________________________________________") message("| |") message("| SOURCING CUSTOM .Rprofile |") message("| |") message("| * qq => quit('no') |") message("| * gg => toggle error = recover/NULL |") message("| * dd => detach this madness |") message("|______________________________________|") message("\n") customCommands <- new.env() assign("qq", structure("no", class = "quitterclass"), envir = customCommands) assign("print.quitterclass", function(quitter) { message(" * quitting, not saving workspace") base::quit(quitter[1L]) }, envir = customCommands) assign("gg", structure("", class = "debuggerclass"), envir = customCommands) assign("print.debuggerclass", function(debugger) { if (!identical(getOption("error"), as.call(list(utils::recover)))) { options(error = recover) message(" * debugging is now ON - option error set to recover") } else { options(error = NULL) message(" * debugging is now OFF - option error set to NULL") } }, envir = customCommands) assign("dd", structure("", class = "detacherclass"), envir = customCommands) assign("print.detacherclass", function(detacher) { detach(customCommands, unload = TRUE, force = TRUE) }) attach(customCommands)
In terminal environments, shortcuts like this can be even more useful:
References
- Rprofile chapter of Efficient R programming
- Documentation on print
- Documentation on options to set and examine a variety of global options.
Today, September 1st 2018 the Constitution of the Slovak Republic celebrates its 26th anniversary. Happy Birthday!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.