<-
виконує призначення в поточному середовищі.
Коли ви знаходитесь у функції, R створює нове середовище для вас. За замовчуванням він включає все з середовища, в якому він був створений, щоб ви могли використовувати і ці змінні, але все, що ви створюєте, не записується в глобальне середовище.
У більшості випадків <<-
буде призначено змінним, що вже є в глобальному середовищі, або створити змінну в глобальному середовищі, навіть якщо ви знаходитесь у функції. Однак це не так просто. Це робить перевірка батьківського середовища на змінну з іменем, що цікавить. Якщо він не знайде його у батьківському середовищі, він переходить до батьківського батьківського середовища (на момент створення функції) і шукає там. Він продовжується вгору до глобального середовища, і якщо його не знайти в глобальному середовищі, він призначить змінну в глобальному середовищі.
Це може ілюструвати, що відбувається.
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
bar <- "in baz - before <<-"
bar <<- "in baz - after <<-"
print(bar)
}
print(bar)
baz()
print(bar)
}
> bar
[1] "global"
> foo()
[1] "in foo"
[1] "in baz - before <<-"
[1] "in baz - after <<-"
> bar
[1] "global"
Перший раз, коли ми друкуємо смужку, ми ще не зателефонували, foo
щоб вона все ще була глобальною - це має сенс. Другий раз, коли ми друкуємо його всередині, foo
перш ніж викликати, baz
тому значення "в foo" має сенс. Далі ми бачимо, що <<-
насправді робить. Наступне значення, що надрукується, - "у базі - до << -", навіть якщо оператор друку надходить після <<-
. Це тому, <<-
що не виглядає в поточному середовищі (якщо ви не знаходитесь в глобальному середовищі, в такому випадку <<-
діє так <-
). Тож усередині baz
значення бар залишається як "in baz - перед << -". Як тільки ми називаємо baz
копію бару всередині foo
змінено на "in baz", але, як ми бачимо, глобальний bar
не змінюється.bar
що визначено всередині foo
знаходиться в батьківському середовищі, коли ми створили, baz
так що це перша копія того, bar
що <<-
бачить, і, таким чином, копія, яку він присвоює. Отже, <<-
це не просто безпосереднє відношення до глобального середовища.
<<-
є складним, і я б не рекомендував використовувати його, якщо ви зможете цього уникнути. Якщо ви дійсно хочете призначити глобальне середовище, ви можете скористатися функцією присвоєння і сказати йому явно, що ви хочете призначити глобально.
Тепер я <<-
змінюю оператор на призначення, і ми можемо побачити, який ефект має:
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
assign("bar", "in baz", envir = .GlobalEnv)
}
print(bar)
baz()
print(bar)
}
bar
#[1] "global"
foo()
#[1] "in foo"
#[1] "in foo"
bar
#[1] "in baz"
Тож обидва рази ми друкуємо смужку всередині foo
значення "в foo" навіть після виклику baz
. Це тому, що assign
ніколи навіть не розглядали копію bar
нутрощів foo, тому що ми точно сказали, де його шукати. Однак цього разу значення бар у глобальному середовищі було змінено, оскільки ми там явно призначили.
Тепер ви також запитали про створення локальних змінних, і ви можете це зробити досить легко, не створюючи функції ... Нам просто потрібно використовувати local
функцію.
bar <- "global"
# local will create a new environment for us to play in
local({
bar <- "local"
print(bar)
})
#[1] "local"
bar
#[1] "global"
globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env
……