В дополнение к другим ответам здесь, которые на самом деле передают ваш объект по ссылке (environment
объекты и ссылочные классы), если вы просто заинтересованы в вызове по ссылке для удобства синтаксиса (т.е. вы не возражаете против ваших данных, скопированных внутрь), вы можете эмулировать это, присваивая окончательное значение внешней переменной при возврате:
byRef <- function(..., envir=parent.frame(), inherits=TRUE) {
cl <- match.call(expand.dots = TRUE)
cl[c(1, match(c("envir", "inherits"), names(cl), 0L))] <- NULL
for (x in as.list(cl)) {
s <- substitute(x)
sx <- do.call(substitute, list(s), envir=envir)
dx <- deparse(sx)
expr <- substitute(assign(dx, s, envir=parent.frame(), inherits=inherits))
do.call(on.exit, list(expr, add=TRUE), envir=envir)
}
}
Тогда мы можем объявить аргументы "call-by-reference":
f <- function(z1, z2, z3) {
byRef(z1, z3)
z1 <- z1 + 1
z2 <- z2 + 2
z3 <- z3 + 3
c(z1, z2, z3)
}
x1 <- 10
x2 <- 20
x3 <- 30
# Values inside:
print(f(x1, x2, x3))
# [1] 11 22 33
# Values outside:
print(c(x1, x2, x3))
# [1] 11 20 33
Обратите внимание, что если вы обращаетесь к переменным «по ссылке» по их внешним именам (x1
, x3
) в любом месте внутри функции, вы получите их еще неизмененные значения извне. Кроме того, эта реализация обрабатывает только простые имена переменных в качестве аргументов, поэтому индексированные аргументы, такие как f(x[1], ...)
, не будут работать (хотя вы, вероятно, могли бы реализовать это с немного более сложной манипуляцией с выражениями, чтобы обойти ограниченное assign
).