Может кто-нибудь объяснить поведение оператора << << - `в R? - PullRequest
0 голосов
/ 17 апреля 2019

Через несколько часов я обнаружил ошибку в своем коде из-за неожиданного поведения оператора операции <<- в r. Я прочитал документацию и просмотрел в интернете, но до сих пор не понимаю поведение оператора.

Посмотрите эти две функции:

# Define a function a_counter
a_counter  <- function(){

  i <<- i + 1
  print(i)

}
> i <- 0
> a_counter()
[1] 1
> print(i)
[1] 1
> a_counter()
[1] 2
> print(i)
[1] 2
# Define a function not_a_counter
not_a_counter  <- function(){

  i <- 0
  i <<- i + 1
  print(i)

}
> i <- 0
> not_a_counter()
[1] 0
> print(i)
[1] 1
> not_a_counter()
[1] 0
> print(i)
[1] 1

Первый фрагмент кода выполняется, как я и ожидал, переменная i в обеих средах (env. Function и global env.) Увеличивается при каждом вызове функции.

Второй кусок кода абсолютно неожидан для меня. i <<- i + 1 не присваивает значение i, расположенному в функциональной среде, но оно делает это в i, расположенном в глобальной среде. Я ожидал, что обе среды будут обновлены.

1 Ответ

4 голосов
/ 17 апреля 2019

В вашем a_counter есть только одно значение i.Не два.Когда в функции обнаруживается «свободная переменная», она ищется в среде, в которой была определена функция.Поэтому, когда вы вызываете i в этой функции, она попадает в глобальную среду, чтобы найти значение.Затем, когда вы делаете <<-, назначение вообще не происходит в функциональной среде.<<- всегда начинает искать в родительской среде.Если вы посмотрите на

counter_vars  <- function() {
  a <- 4 
  i <<- i + 1
  ls() 
}
counter_vars()
# [1] "a"

, то увидите, что единственная переменная внутри функции environment / closure - это переменная a.Переменная i там не существует.Таким образом, с исходной функцией все i происходят из глобальной области видимости

a_counter  <- function(){    
  i <<- i + 1    # global i = global i + 1
  print(i)       # global i still (no local variable has been created)
}

Так что поведение, которое вы видите в not_a_counter, следует ожидать, потому что <<- не изменит значения в текущей среде.Это всегда начинает искать одну среду "вверх".Если у вас есть

not_a_counter  <- function(){    
  i <- 0         # local i (always 0)
  i <<- i + 1    # global i == local i + 1 (always 0+1)
  print(i)       # local i (always still 0, local value not changed)
}

Переменная i больше не «свободна», как только вы определите ее в функции.Таким образом, i <- 0 создает локальную переменную, в части i <<- i + 1, правая часть i+1 использует эту локальную переменную и присваивает i в родительской среде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...