Я только что закончил читать об обзоре во введении R и очень любопытен на предмет <<-
присвоение.
Руководство показало один (очень интересный) пример для <<-
, который я чувствую, что понял. То, что я все еще пропускаю, является контекстом того, когда это может быть полезно.
Таким образом, что я хотел бы считать от Вас, примеры (или ссылки на примеры) на когда использование <<-
может быть интересным/полезным. Что могло бы быть опасностями использовать его (выглядит легким освободить дорожку), и любые подсказки, которые Вы могли бы испытывать желание совместно использовать.
<< -
наиболее полезно в сочетании с закрытием для поддержания состояния. Вот отрывок из моей недавней статьи:
Замыкание - это функция, написанная другой функцией. Замыкания называются так потому, что они охватывают среду родительской функции и могут получить доступ ко всем переменным и параметрам в этой функции. Это полезно, потому что позволяет нам иметь два уровня параметров. Один уровень параметров (родительский) контролирует работу функции. Другой уровень (ребенок) выполняет работу. В следующем примере показано, как можно использовать эту идею для создания семейства степенных функций. Родительская функция ( power
) создает дочерние функции ( square
и cube
), которые фактически выполняют тяжелую работу.
power <- function(exponent) {
function(x) x ^ exponent
}
square <- power(2)
square(2) # -> [1] 4
square(4) # -> [1] 16
cube <- power(3)
cube(2) # -> [1] 8
cube(4) # -> [1] 64
Возможность управлять переменными на двух уровнях также позволяет поддерживать состояние между вызовами функций, позволяя функции изменять переменные в среде своего родителя. Ключом к управлению переменными на разных уровнях является оператор присваивания с двойной стрелкой << -
. В отличие от обычного назначения одиночной стрелки ( <-
), которое всегда работает на текущем уровне, оператор двойной стрелки может изменять переменные на родительских уровнях.
Это позволяет поддерживать счетчик, который записывает, сколько раз функция была вызвана, как показано в следующем примере. Каждый раз, когда new_counter
запускается, он создает среду, инициализирует счетчик i
в этой среде, а затем создает новую функцию.
new_counter <- function() {
i <- 0
function() {
# do something useful, then ...
i <<- i + 1
i
}
}
Новая функция - это замыкание, а ее окружение - это окружающая среда. Когда выполняются закрытия counter_one
и counter_two
, каждое из них изменяет счетчик в своей окружающей среде, а затем возвращает текущий счет.
counter_one <- new_counter()
counter_two <- new_counter()
counter_one() # -> [1] 1
counter_one() # -> [1] 2
counter_two() # -> [1] 1
f <- function(n, x0) {x <- x0; replicate(n, (function(){x <<- x+rnorm(1)})())}
plot(f(1000,0),typ="l")
Это помогает думать о << -
как о эквиваленте ] назначить
(если вы установите для параметра наследует
в этой функции значение ИСТИНА
). Преимущество assign
заключается в том, что он позволяет указать больше параметров (например, среду), поэтому в большинстве случаев я предпочитаю использовать assign
вместо << -
.
Использование << -
и assign (x, value, inherits = TRUE)
означает, что «окружающие среды предоставленной среды ищутся до тех пор, пока не будет обнаружена переменная 'x'.«Другими словами, он будет продолжать просматривать среды по порядку, пока не найдет переменную с таким именем и не присвоит ее этому. Это может быть в рамках функции или в глобальной среде.
Чтобы понять, что делают эти функции, вам также необходимо разбираться в среде R (например, используя search
).
Я регулярно использую эти функции, когда запускаю большое моделирование, и я хочу сохранить промежуточные результатов. Это позволяет вам создать объект вне области действия данной функции или цикла apply
. Это очень полезно, особенно если вас беспокоит неожиданное завершение большого цикла (например, отключение базы данных) в в этом случае вы можете потерять все в процессе. Это было бы эквивалентно записи ваших результатов в базу данных или файл во время длительного процесса, за исключением того, что вместо этого он сохраняет результаты в среде R.
Мое основное предупреждение с этим : будьте осторожны, потому что теперь вы ж работа с глобальными переменными, особенно при использовании << -
. Это означает, что вы можете столкнуться с ситуациями, когда функция использует значение объекта из среды, когда вы ожидали, что она будет использовать значение, указанное в качестве параметра. Это одна из основных вещей, которых функциональное программирование пытается избежать (см. побочные эффекты ).Я избегаю этой проблемы, присваивая свои значения уникальным именам переменных (с использованием вставки с заданными или уникальными параметрами), которые никогда не используются в функции, но используются только для кеширования, и в случае, если мне нужно восстановить позже (или выполнить некоторые мета -анализ промежуточных результатов).
Одно место, где я использовал <<-
, было в простых графических интерфейсах с использованием tcl/tk. В некоторых начальных примерах он есть - так как вам нужно сделать различие между локальными и глобальными переменными для сохранения состояния. Смотрите, например,
library(tcltk)
demo(tkdensity)
в котором используется <<-
. В остальном я согласен с Мареком :) -- поиск в Google может помочь.