<- 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, fooportanto ainda deve ser global - isso faz sentido. Na segunda vez em que imprimimos, fooantes 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 bazvalor da barra permanece como "in baz - before << -". Depois que chamamos baza cópia da barra dentro de fooé alterada para "in baz", mas como podemos ver, o global barpermanece inalterado.barque é definido dentro de fooestá no ambiente pai quando criamos, bazportanto esta é a primeira cópia do barque <<-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 foovalor, "in foo", mesmo após a chamada baz. Isso ocorre porque assignnunca consideramos a cópia de bardentro 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 localfunçã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,…