Как Вы используете “<<-” (обзор присвоения) в R?

Я только что закончил читать об обзоре во введении R и очень любопытен на предмет <<- присвоение.

Руководство показало один (очень интересный) пример для <<-, который я чувствую, что понял. То, что я все еще пропускаю, является контекстом того, когда это может быть полезно.

Таким образом, что я хотел бы считать от Вас, примеры (или ссылки на примеры) на когда использование <<- может быть интересным/полезным. Что могло бы быть опасностями использовать его (выглядит легким освободить дорожку), и любые подсказки, которые Вы могли бы испытывать желание совместно использовать.

122
задан Bhargav Rao 15 March 2016 в 14:43
поделиться

4 ответа

<< - наиболее полезно в сочетании с закрытием для поддержания состояния. Вот отрывок из моей недавней статьи:

Замыкание - это функция, написанная другой функцией. Замыкания называются так потому, что они охватывают среду родительской функции и могут получить доступ ко всем переменным и параметрам в этой функции. Это полезно, потому что позволяет нам иметь два уровня параметров. Один уровень параметров (родительский) контролирует работу функции. Другой уровень (ребенок) выполняет работу. В следующем примере показано, как можно использовать эту идею для создания семейства степенных функций. Родительская функция ( 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
170
ответ дан 24 November 2019 в 01:24
поделиться
f <- function(n, x0) {x <- x0; replicate(n, (function(){x <<- x+rnorm(1)})())}
plot(f(1000,0),typ="l")
4
ответ дан 24 November 2019 в 01:24
поделиться

Это помогает думать о << - как о эквиваленте ] назначить (если вы установите для параметра наследует в этой функции значение ИСТИНА ). Преимущество assign заключается в том, что он позволяет указать больше параметров (например, среду), поэтому в большинстве случаев я предпочитаю использовать assign вместо << - .

Использование << - и assign (x, value, inherits = TRUE) означает, что «окружающие среды предоставленной среды ищутся до тех пор, пока не будет обнаружена переменная 'x'.«Другими словами, он будет продолжать просматривать среды по порядку, пока не найдет переменную с таким именем и не присвоит ее этому. Это может быть в рамках функции или в глобальной среде.

Чтобы понять, что делают эти функции, вам также необходимо разбираться в среде R (например, используя search ).

Я регулярно использую эти функции, когда запускаю большое моделирование, и я хочу сохранить промежуточные результатов. Это позволяет вам создать объект вне области действия данной функции или цикла apply . Это очень полезно, особенно если вас беспокоит неожиданное завершение большого цикла (например, отключение базы данных) в в этом случае вы можете потерять все в процессе. Это было бы эквивалентно записи ваших результатов в базу данных или файл во время длительного процесса, за исключением того, что вместо этого он сохраняет результаты в среде R.

Мое основное предупреждение с этим : будьте осторожны, потому что теперь вы ж работа с глобальными переменными, особенно при использовании << - . Это означает, что вы можете столкнуться с ситуациями, когда функция использует значение объекта из среды, когда вы ожидали, что она будет использовать значение, указанное в качестве параметра. Это одна из основных вещей, которых функциональное программирование пытается избежать (см. побочные эффекты ).Я избегаю этой проблемы, присваивая свои значения уникальным именам переменных (с использованием вставки с заданными или уникальными параметрами), которые никогда не используются в функции, но используются только для кеширования, и в случае, если мне нужно восстановить позже (или выполнить некоторые мета -анализ промежуточных результатов).

33
ответ дан 24 November 2019 в 01:24
поделиться

Одно место, где я использовал <<-, было в простых графических интерфейсах с использованием tcl/tk. В некоторых начальных примерах он есть - так как вам нужно сделать различие между локальными и глобальными переменными для сохранения состояния. Смотрите, например,

 library(tcltk)
 demo(tkdensity)

в котором используется <<-. В остальном я согласен с Мареком :) -- поиск в Google может помочь.

8
ответ дан 24 November 2019 в 01:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: