<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/r-tip-be-wary-of/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.win-vector.com/blog/2018/06/r-tip-be-wary-of/"> R – Win-Vector Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><a rel="nofollow" href="http://www.win-vector.com/blog/tag/r-tips/" target="_blank">R Tip</a>: be wary of “<code>...</code>“.</p>
<p>The following code example contains an easy error in using the <a rel="nofollow" href="https://www.r-project.org/" target="_blank">R</a> function <code>unique()</code>.</p>
<pre>
vec1 &lt;- c(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)
vec2 &lt;- c(&quot;c&quot;, &quot;d&quot;)
unique(vec1, vec2)
# [1] &quot;a&quot; &quot;b&quot; &quot;c&quot;
</pre>
<p>Notice none of the novel values from <code>vec2</code> are present in the result. Our mistake was: we (improperly) tried to use <code>unique()</code> with multiple value arguments, as one would use <code>union()</code>. Also notice no error or warning was signaled. We used <code>unique()</code> incorrectly and nothing pointed this out to us. What compounded our error was <code>R</code>‘s “<code>...</code>” function signature feature.</p>
<p>In this note I will talk a bit about how to defend against this kind of mistake. I am going to apply the principle that a design that makes committing mistakes more difficult (or even impossible) is a good thing, and not a sign of carelessness, laziness, or weakness. I am well aware that every time I admit to making a mistake (I have indeed made the above mistake) those who claim to never make mistakes have a laugh at my expense. Honestly I feel the reason I <em>see</em> more mistakes is I check a lot more.</p>
<p><span></span></p>
<p>
<p>Data science coding is often done in a rush (deadlines, wanting to see results, and so on). Instead of moving fast, let’s take the time to think a bit about programming theory using a very small concrete issue. This lets us show how one can work a bit safer (saving time in the end), without sacrificing notational power or legibility.</p>
<p>A confounding issue is: <code>unique()</code> failed to alert me of my mistake because, <code>unique()</code>‘s function signature (like so many <code>R</code> functions) includes a “<code>...</code>” argument. I might have been careless or in a rush, but it seems like <code>unique</code> was also in a rush and did not care to supply argument inspection.</p>
<p>In <code>R</code> a function that includes a “<code>...</code>” in its signature will accept arbitrary arguments and values in addition to the ones explicitly declared and documented. There are three primary uses of “<code>...</code>” in <code>R</code>: accepting unknown arguments that are to be passed to later functions, building variadic functions, and forcing later arguments to be bound by name (<em>my</em> <a rel="nofollow" href="http://www.win-vector.com/blog/2018/02/r-tip-force-named-arguments/" target="_blank">favorite use</a>). Unfortunately, “<code>...</code>” is also often used to avoid documenting arguments and turns off a lot of very useful error checking.</p>
<p>An example of the “accepting unknown arguments” use is <code>lapply()</code>. <code>lapply()</code> passes what it finds in “<code>...</code>” to whatever function it is working with. For example:</p>
<pre>
lapply(c(&quot;a&quot;, &quot;b&quot;), paste, &quot;!&quot;, sep = &quot;&quot;)
# [[1]]
# [1] &quot;a!&quot;
# 
# [[2]]
# [1] &quot;b!&quot;
</pre>
<p>Notice the arguments “&quot;!&quot;, sep = &quot;&quot;” were passed on to <code>paste()</code>. Since <code>lapply()</code> can not know what function the user will use ahead of time it uses the “<code>...</code>” abstraction to forward arguments. Personally I never use this form and tend to write the somewhat more explicit and verbose style shown below.</p>
<pre>
lapply(c(&quot;a&quot;, &quot;b&quot;), 
   function(vi) { paste(vi, &quot;!&quot;, sep = &quot;&quot;) })
</pre>
<p>I feel this form is more readable as the arguments are seen where they are actually used. (Note: this, is a notional example- in practice we would use “<code>paste0(c(&quot;a&quot;, &quot;b&quot;), &quot;!&quot;)</code>” to directly produce the result as a vector.)</p>
<p>An example of using “<code>...</code>” to supply a variadic interface is <code>paste()</code> itself.</p>
<pre>
paste(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)
# [1] &quot;a b c&quot;
</pre>
<p>Other important examples include <code>list()</code> and <code>c()</code>. In fact I like <code>list()</code> and <code>c()</code> as they only take a “<code>...</code>” and no other arguments. Being variadic is so important to <code>list()</code> and <code>c()</code> is that is essentially all they do. One can often separate out the variadic intent with lists or vectors as in:</p>
<pre>
paste(c(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;), collapse = &quot; &quot;)
# [1] &quot;a b c&quot;
</pre>
<p>Even I don’t write code such as the above (that is too long even for me), <em>unless</em> the values are coming from somewhere else (such as a variable). However with <a rel="nofollow" href="https://cran.r-project.org/package=wrapr" target="_blank"><code>wrapr</code></a>‘s <a rel="nofollow" href="https://winvector.github.io/wrapr/reference/reduceexpand.html" target="_blank">reduce/expand</a> operator we can completely separate the collection of variadic arguments and their application. The notation looks like the following:</p>
<pre>
library(&quot;wrapr&quot;)

values &lt;- c(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)
values %.|% paste
# [1] &quot;a b c&quot;
</pre>
<p>Essentially <a rel="nofollow" href="https://winvector.github.io/wrapr/reference/reduceexpand.html" target="_blank">reduce/expand</a> calls variadic functions with items taken from a vector or list as individual arguments (allowing one to program easily over variadic functions). <code>%.|%</code> is intended to place values in the “<code>...</code>” slot of a function (the variadic term). It is designed for a more perfect world where when a function declares “<code>...</code>” in its signature it is then the only user facing part of the signature. This is hardly ever actually the case in <code>R</code> as common functions such as <code>paste()</code> and <code>sum()</code> have additional optional named arguments (which we are here leaving at their default values), whereas <code>c()</code> and <code>list()</code> are pure (take only “<code>...</code>“).</p>
<p>With a few non-standard (name capturing) and variadic value constructors one does not in fact <em>need</em> other functions to be name capturing or variadic. With such tools one can have these conveniences everywhere. For example we can convert our incorrect use of <code>unique()</code> into correct code using <code>c()</code>.</p>
<pre>
unique(c(vec1, vec2))
# [1] &quot;a&quot; &quot;b&quot; &quot;c&quot; &quot;d&quot;
</pre>
<p>In the above code roles are kept separate: <code>c()</code> is collecting values and <code>unique()</code> is applying a calculation. We don’t need a powerful “super unique” or “super union” function, <code>unique()</code> is good enough if we remember to use <code>c()</code>.</p>
<p>In the spirit of our <a rel="nofollow" href="http://www.win-vector.com/blog/2018/02/r-tip-force-named-arguments/" target="_blank">earlier article on function argument names</a> we have defined a convenience function <code>wrapr::uniques()</code> that enforces the use of value carrying arguments. With <code>wrapr::uniques()</code> if one attempts the mistake I have been discussing one immediately gets a signaling error (instead of propagating incorrect calculations forward).</p>
<pre>
library(&quot;wrapr&quot;)

uniques(c(vec1, vec2))
# [1] &quot;a&quot; &quot;b&quot; &quot;c&quot; &quot;d&quot;

uniques(vec1, vec2)
# Error: wrapr::uniques unexpected arguments: vec2 
</pre>
<p>With <code>uniques()</code> we either get the right answer, or we get immediately stopped at the mistaken step. This is a good way to work.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.win-vector.com/blog/2018/06/r-tip-be-wary-of/"> R – Win-Vector Blog</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/VzVt--OLKVM" height="1"></a></div>