In various places, from the R help pages to books to course materials, you see R code like
(x = runif(10, 0, 10))
## [1] 1.610466 2.662462 1.517036 1.372483 4.272460 6.402148 8.347196
## [8] 8.775537 1.863104 8.912241
which displays the value of x
. Without the brackets, it doesn’t. Harkanwal Singh, on Twitter, said “I would like to know more”. So, in case he’s not the only one, this is what’s going on.
First, when you evaluate an expression in R it will usually return a value, which will be printed.
exp(pi)
## [1] 23.14069
rnorm(2)
## [1] -0.4578773 1.2234183
cos
## function (x) .Primitive("cos")
function(x,y) {
lm(y~x)
}
## function(x,y) {
## lm(y~x)
## }
The printing doesn’t always happen, for example:
boxplot(x)
Is this because boxplot
doesn’t return a value? No!
a<-boxplot(x)
a
## $stats
## [,1]
## [1,] 1.372483
## [2,] 1.610466
## [3,] 3.467461
## [4,] 8.347196
## [5,] 8.912241
##
## $n
## [1] 10
##
## $conf
## [,1]
## [1,] 0.1015223
## [2,] 6.8333997
##
## $out
## numeric(0)
##
## $group
## numeric(0)
##
## $names
## [1] "1"
The value returned by boxplot
is somehow invisible, but only in a temporary way. In fact, if you look near the end of the boxplot.default
method, you see
if (is.null(pars$boxfill) && is.null(args$boxfill))
pars$boxfill <- col
do.call("bxp", c(list(z, notch = notch, width = width,
varwidth = varwidth, log = log, border = border,
pars = pars, outline = outline, horizontal = horizontal,
add = add, at = at), args[namedargs]))
invisible(z)
The value is returned, and tagged as invisible. It won’t print, at least not until you do something to it.1
There are two uses of the invisibility flag that are critical to usability of R but not obvious. The first is in assignments. If you type something like
bigx <- matrix(rnorm(1e6),ncol=100)
you really don’t want bigx
to automatically print. But it would, without more effort: these are perfectly good expressions that return a value.
Even worse, you don’t want
print(x)
## [1] 1.610466 2.662462 1.517036 1.372483 4.272460 6.402148 8.347196
## [8] 8.775537 1.863104 8.912241
to print its returned value, because its returned value is typically the value of x
and that way lies infinite loops. Methods for print
typically return invisible(x)
2. You could also get around this by having print
not return a value, but that breaks the magic variable .Last.value
and, anyway, it’s not what we do.
And, finally, what’s with the parentheses? The parentheses are a function
get("(")
## .Primitive("(")
It returns its argument unchanged, and, like most functions, it doesn’t set the invisibility flag. So when you type
(x = runif(10,0,10))
## [1] 6.9129134 0.1128086 6.3230912 0.6280404 7.9812971 5.5740664 4.9418995
## [8] 0.8299477 2.8720316 0.1819464
the inner assignment is evaluated, the value is returned invisibly, the value is passed to the (
function, this returns the same value, but it doesn’t set the invisibility flag, and the vector prints.
My recollection is that this wasn’t ever a deliberate plan, and there was a move to get rid of it at some point long ago, which was stopped partly because the trick was being used in so many base R help pages.