<-
faz atribuição no ambiente atual.
Quando você está dentro de uma função, R cria um novo ambiente para você. Por padrão, inclui tudo, desde o ambiente em que foi criado, para que você possa usar essas variáveis também, mas qualquer coisa nova que você criar não será gravada no ambiente global.
Na maioria dos casos <<-
, atribuirá a variáveis que já estão no ambiente global ou criará uma variável no ambiente global, mesmo se você estiver dentro de uma função. No entanto, não é tão simples assim. O que ele faz é verificar no ambiente pai uma variável com o nome de interesse. Se ele não o encontrar no ambiente pai, ele será direcionado ao pai do ambiente pai (no momento em que a função foi criada) e procurado lá. Ele continua ascendendo ao ambiente global e, se não for encontrado no ambiente global, atribuirá a variável ao ambiente global.
Isso pode ilustrar o que está acontecendo.
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"
A primeira vez que imprimimos barra, ainda não ligamos, foo
portanto ainda deve ser global - isso faz sentido. Na segunda vez em que imprimimos, foo
antes de chamar baz
, o valor "in foo" faz sentido. A seguir, é onde vemos o que <<-
realmente está fazendo. O próximo valor impresso é "in baz - before << -", mesmo que a instrução print venha após o <<-
. Isso ocorre porque <<-
não parece no ambiente atual (a menos que você esteja no ambiente global, caso em que <<-
atua como <-
). Portanto, dentro do baz
valor da barra permanece como "in baz - before << -". Depois que chamamos baz
a cópia da barra dentro de foo
é alterada para "in baz", mas como podemos ver, o global bar
permanece inalterado.bar
que é definido dentro de foo
está no ambiente pai quando criamos, baz
portanto esta é a primeira cópia do bar
que <<-
vê e, portanto, a cópia à qual ele atribui. Portanto, <<-
não é apenas atribuir diretamente ao ambiente global.
<<-
é complicado e eu não recomendaria usá-lo se você puder evitá-lo. Se você realmente deseja atribuir ao ambiente global, pode usar a função de atribuição e informar explicitamente que deseja atribuir globalmente.
Agora eu mudo <<-
para uma declaração de atribuição e podemos ver qual efeito isso tem:
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"
Portanto, nas duas vezes em que imprimimos a barra dentro do foo
valor, "in foo", mesmo após a chamada baz
. Isso ocorre porque assign
nunca consideramos a cópia de bar
dentro de foo porque dissemos exatamente onde procurar. No entanto, desta vez, o valor da barra no ambiente global foi alterado porque atribuímos explicitamente lá.
Agora você também perguntou sobre a criação de variáveis locais e pode fazer isso com bastante facilidade, sem criar uma função ... Só precisamos usar a local
função.
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
,…