promises
When an argument is passed to a function it is not passed as a value but is passed as a promise which consists of
- the expression or code that the caller uses as the actual argument
- the environment in which that expression is to be evaluated, viz. the caller's environment.
- the value that the expression represents when the expression is evaluated in the promise's environment -- this slot is not filled in until the promise is actually evaluated. It will never be filled in if the function never accesses it.
The pryr package can show the info in a promise:
library(pryr)
g <- function(x) promise_info(x)
g(ggplot2)
giving:
$code
ggplot2 <-- the promise x represents the expression ggplot2
$env
<environment: R_GlobalEnv> <-- if evaluated it will be done in this environment
$evaled
[1] FALSE <-- it has not been evaluated
$value
NULL <-- not filled in because promise has not been evaluated
The only one of the above slots in the pryr output that can be accessed at the R level without writing a C function to do it (or using a package such as pryr that accesses such C code) is the code slot. That can be done using the R function substitute(x)
(or other means). In terms of the pryr output substitute
applied to a promise returns the code slot without evaluating the promise. That is, the value slot is not modified. Had we accessed x
in an ordinary way, i.e. not via substitute
, then the code would have been evaluated in the promise's environment, stored in the value slot and then passed to the expression in the function that accesses it.
Thus either of the following result in a character string representing what was passed as an expression, i.e. the character representation of the code slot, as opposed to its value.
f <- function(x) as.character(substitute(x))
f("ggplot2")
## [1] "ggplot2"
f(ggplot2)
## [1] "ggplot2"
library
In fact, library
uses this idiom, i.e. as.character(substitute(x))
, to handle its first argument.
aes
The aes
function uses match.call
to get the entire call as an expression and so in a sense is an alternative to substitute
. For example:
h <- function(x) match.call()
h(pi + 3)
## h(x = pi + 3)
Note
One cannot tell without looking at the documentation or code of a function how it will treat its arguments.