<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/crafty-tricks-no-more-typing-brackets/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://jozefhajnala.gitlab.io/r/r903-tricks-bracketless/"> Jozef's Rblog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>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.</p>
<div>
<h1>Work in R faster with custom bracketless commands</h1>
<p>A good starting example is, well, quitting R altogether. Usually, one may do:</p>
<pre><code>quit()</code></pre>
<p>Which will in turn likely get you and extra question regarding saving a workspace image. So you then finally type <code>n</code> and are done with it. If you want to be a bit faster, you may do:</p>
<pre><code>q(&quot;no&quot;)</code></pre>
<p>Better, but still an awful lot of typing just to quit <code>R</code>, especially when working in a terminal-like environment with multiple sessions.</p>
<blockquote>
<p>Let us be a bit craftier and make <code>R</code> quit just by typing <code>qq</code></p>
</blockquote>
<p>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.</p>
<p>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:</p>
<pre><code>qq &lt;- structure(&quot;no&quot;, class = &quot;quitter&quot;)
print.quitter &lt;- function(quitter) base::quit(&quot;no&quot;)

# This will quit your session NOT saving a workspace image!
qq</code></pre>
<div>
<img alt="Oopsâ€¦I Did It Again" src="https://i2.wp.com/jozefhajnala.gitlab.io/r/img/r903-01-ooops.gif?w=456&ssl=1" data-recalc-dims="1">
<p>Oopsâ€¦I Did It Again</p>
</div>
</div>
<div>
<h1>Switching debugging modes with ease</h1>
<p>Quitting <code>R</code> 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.</p>
<p>One example I use very frequently is to change the <code>error</code> option, which governs how <code>R</code> behaves when encountering non-catastrophic errors such as those generated by <code>stop</code>, etc.</p>
<ul>
<li>I find setting the option to <code>options(error = utils::recover)</code> very useful for debugging and at the same time very annoying when undesired.</li>
<li>Typing <code>options(error = NULL)</code> to change it back is however even more annoying. Or is it <code>options(&quot;error&quot;) = NULL</code>? Or maybe even <code>options(error) = NULL</code>?</li>
</ul>
<p>In comes the <code>gg</code> shortcut:</p>
<pre><code>gg &lt;- structure(FALSE, class = &quot;debuggerclass&quot;)
print.debuggerclass &lt;-  function(debugger) {
  if (!identical(getOption(&quot;error&quot;), as.call(list(utils::recover)))) {
    options(error = recover)
    message(&quot; * debugging is now ON - option error set to recover&quot;)
  } else {
    options(error = NULL)
    message(&quot; * debugging is now OFF - option error set to NULL&quot;)
  }
}</code></pre>
<p>Now we switch between the options with ease:</p>
<pre><code># When in need of debugging
gg</code></pre>
<pre><code>##  * debugging is now ON - option error set to recover</code></pre>
<pre><code># The option is now set to recover
getOption(&quot;error&quot;)</code></pre>
<pre><code>## (function () 
## {
##     if (.isMethodsDispatchOn()) {
##         tState &lt;- tracingState(FALSE)
##         on.exit(tracingState(tState))
##     }
##     calls &lt;- sys.calls()
##     from &lt;- 0L
##     n &lt;- length(calls)
##     if (identical(sys.function(n), recover)) 
##         n &lt;- n - 1L
##     for (i in rev(seq_len(n))) {
##         calli &lt;- calls[[i]]
##         fname &lt;- calli[[1L]]
##         if (!is.na(match(deparse(fname)[1L], c(&quot;methods::.doTrace&quot;, 
##             &quot;.doTrace&quot;)))) {
##             from &lt;- i - 1L
##             break
##         }
##     }
##     if (from == 0L) 
##         for (i in rev(seq_len(n))) {
##             calli &lt;- calls[[i]]
##             fname &lt;- calli[[1L]]
##             if (!is.name(fname) || is.na(match(as.character(fname), 
##                 c(&quot;recover&quot;, &quot;stop&quot;, &quot;Stop&quot;)))) {
##                 from &lt;- i
##                 break
##             }
##         }
##     if (from > 0L) {
##         if (!interactive()) {
##             try(dump.frames())
##             cat(gettext(&quot;recover called non-interactively; frames dumped, use debugger() to view\n&quot;))
##             return(NULL)
##         }
##         else if (identical(getOption(&quot;show.error.messages&quot;), 
##             FALSE)) 
##             return(NULL)
##         calls &lt;- limitedLabels(calls[1L:from])
##         repeat {
##             which &lt;- menu(calls, title = &quot;\nEnter a frame number, or 0 to exit  &quot;)
##             if (which) 
##                 eval(substitute(browser(skipCalls = skip), list(skip = 7 - 
##                   which)), envir = sys.frame(which))
##             else break
##         }
##     }
##     else cat(gettext(&quot;No suitable frames for recover()\n&quot;))
## })()</code></pre>
<pre><code># When done debugging
gg </code></pre>
<pre><code>##  * debugging is now OFF - option error set to NULL</code></pre>
<pre><code># The option is now back to NULL
getOption(&quot;error&quot;)</code></pre>
<pre><code>## NULL</code></pre>
</div>
<div>
<h1>Making it practical (and a bit less barbaric)</h1>
<p>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:</p>
<ol>
<li>Adding the definitions into our <code>.Rprofile</code> with a proper notice, which will run the definitions and make the shortcuts available every time we start R standardly</li>
<li>Enclosing the definitions into a separate environment attached to the search path, potentially with a command to detach it easily</li>
</ol>
<p>Such an <code>.Rprofile</code> can look similar to:</p>
<pre><code>message(&quot;________________________________________&quot;)
message(&quot;|                                      |&quot;)
message(&quot;|      SOURCING CUSTOM .Rprofile       |&quot;)
message(&quot;|                                      |&quot;)
message(&quot;|  * qq => quit('no')                  |&quot;)
message(&quot;|  * gg => toggle error = recover/NULL |&quot;)
message(&quot;|  * dd => detach this madness         |&quot;)
message(&quot;|______________________________________|&quot;)
message(&quot;\n&quot;)

customCommands &lt;- new.env()

assign(&quot;qq&quot;, structure(&quot;no&quot;, class = &quot;quitterclass&quot;), envir = customCommands)
assign(&quot;print.quitterclass&quot;, function(quitter) {
  message(&quot; * quitting, not saving workspace&quot;)
  base::quit(quitter[1L])
}, envir = customCommands)

assign(&quot;gg&quot;, structure(&quot;&quot;, class = &quot;debuggerclass&quot;), envir = customCommands)
assign(&quot;print.debuggerclass&quot;, function(debugger) {
  if (!identical(getOption(&quot;error&quot;), as.call(list(utils::recover)))) {
    options(error = recover)
    message(&quot; * debugging is now ON - option error set to recover&quot;)
  } else {
    options(error = NULL)
    message(&quot; * debugging is now OFF - option error set to NULL&quot;)
  }
}, envir = customCommands)

assign(&quot;dd&quot;, structure(&quot;&quot;, class = &quot;detacherclass&quot;), envir = customCommands)
assign(&quot;print.detacherclass&quot;, function(detacher) {
  detach(customCommands, unload = TRUE, force = TRUE)
})

attach(customCommands)</code></pre>
<p>In terminal environments, shortcuts like this can be even more useful:</p>
<div>
<img alt="Tends to be more useful in the terminal" src="https://i0.wp.com/jozefhajnala.gitlab.io/r/img/r903-02-terminal.gif?w=456&ssl=1" data-recalc-dims="1">
<p>Tends to be more useful in the terminal</p>
</div>
</div>
<div>
<h1>References</h1>
<ol>
<li><a rel="nofollow" href="https://csgillespie.github.io/efficientR/3-3-r-startup.html#rprofile" target="_blank">Rprofile chapter</a> of Efficient R programming</li>
<li><a rel="nofollow" href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/print.html" target="_blank">Documentation on print</a></li>
<li><a rel="nofollow" href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/options.html" target="_blank">Documentation on options</a> to set and examine a variety of global options.</li>
</ol>
<blockquote>
<p><img alt="Flag of Slovakia" width="40" align="left" src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Coat_of_arms_of_Slovakia.svg">Today, September 1st 2018 the <a rel="nofollow" href="https://en.wikipedia.org/wiki/Constitution_of_Slovakia" target="_blank">Constitution of the Slovak Republic</a> celebrates its 26th anniversary. Happy Birthday!</p>
</blockquote>
<h2>Did you find the article helpful or interesting? Help others find it by sharing</h2>
<div></div>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://jozefhajnala.gitlab.io/r/r903-tricks-bracketless/"> Jozef's Rblog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/HpaILl_d-ac" height="1"></a></div>