В чем разница между assign() и << - in R?
Обычный подход к написанию функций в R (как я понимаю) заключается в том, чтобы избежать побочных эффектов и вернуть значение из функции.
contained <- function(x) {
x_squared <- x^2
return(x_squared)
}
В этом случае возвращается значение, вычисленное из ввода в функцию. Но переменная x_squared
недоступна.
Но если вам нужно нарушить этот базовый принцип функционального программирования (и я не уверен, насколько серьезным R является эта проблема) и вернуть объект из функции, у вас есть два варианта.
escape <- function(x){
x_squared <<- x^2
assign("x_times_x", x*x, envir = .GlobalEnv)
}
Возвращаются оба объекта x_squared
и x_times_x
. Является ли один метод предпочтительным для другого и почему так?
Ответы
Ответ 1
Томас Ламли отвечает на этот в превосходной должности в r-help на днях. <<-
относится к окружению, поэтому вы можете делать что-то подобное (и снова цитирую его сообщение с 22 апреля в этом потоке):
make.accumulator<-function(){
a <- 0
function(x) {
a <<- a + x
a
}
}
> f<-make.accumulator()
> f(1)
[1] 1
> f(1)
[1] 2
> f(11)
[1] 13
> f(11)
[1] 24
Это законное использование <<-
как "супер-присвоение" с лексической областью. И не просто назначить в глобальной среде. Для этого у Тома есть такие слова выбора:
Зло и Неправильное использование - изменить переменные в глобальной среде.
Очень хороший совет.
Ответ 2
В соответствии с страницей руководства здесь,
Операторы <<-
и ->>
вызывают поиск в среде для определения существующего определения назначаемой переменной.
Мне никогда не приходилось делать это на практике, но, на мой взгляд, assign
выигрывает много очков, чтобы точно определить среду, даже не задумываясь о правилах R-обзора. <<-
выполняет поиск через среды и поэтому немного сложнее интерпретировать.
EDIT: в отношении к @Dirk и @Hadley это звучит так: assign
- это подходящий способ присвоить глобальную среду (когда это то, что вы знаете, вы хотите), а <<-
- это подходящий способ "поднять" до более широкой области.
Ответ 3
Как отметил @John в своем ответе, присваивание позволяет вам конкретно указать среду. Конкретное приложение будет выглядеть следующим образом:
testfn <- function(x){
x_squared <- NULL
escape <- function(x){
x_squared <<- x^2
assign("x_times_x", x*x, envir = parent.frame(n = 1))
}
escape(x)
print(x_squared)
print(x_times_x)
}
где мы используем как <<-
, так и assign
. Обратите внимание, что если вы хотите использовать <<-
для назначения окружению функции верхнего уровня, вам нужно объявить/инициализировать переменную. Однако с помощью assign
вы можете использовать parent.frame(1)
для указания инкапсулирующей среды.