Replacement functions, such as names<-
, seem to not use lazy evaluation when called like names(x) <- c("a", "b")
.
To demonstrate, let’s define a function to get the fractional part of a number and a corresponding replacement function – but inside the replacement function, include a line to print the defused value
argument.
fractional <- function(x) {
x %% 1
}
`fractional<-` <- function(x, value) {
print(rlang::enexpr(value))
invisible(x %/% 1 + value)
}
Now if we call fractional<-
directly, it prints the expression we gave for value
:
x <- 10.1
`fractional<-`(x, 0.2 + 0.2)
#> 0.2 + 0.2
But if we call it like in the assignment form, it prints the result of evaluating the expression:
x <- 10.1
fractional(x) <- 0.2 + 0.2
#> [1] 0.4
The language definition explains replacement functions like:
names(x) <- c("a","b")
is equivalent to
`*tmp*` <- x x <- "names<-"(`*tmp*`, value=c("a","b")) rm(`*tmp*`)
But this doesn’t reproduce this behavior:
x <- 10.1
`*tmp*` <- x
x <- "fractional<-"(`*tmp*`, value=0.2 + 0.2)
rm(`*tmp*`)
#> [1] 0.4
What is happening internally in <-
that makes it so that value
is passed to fractional<-
after being evaluated, and is there any way to circumvent this behavior?