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!
Did you find the article helpful or interesting? Help others find it by sharing
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.