<-
không phân công trong môi trường hiện tại.
Khi bạn ở trong hàm R sẽ tạo một môi trường mới cho bạn. Theo mặc định, nó bao gồm mọi thứ từ môi trường mà nó được tạo để bạn có thể sử dụng các biến đó nhưng mọi thứ mới bạn tạo sẽ không được ghi vào môi trường toàn cầu.
Trong hầu hết các trường hợp <<-
sẽ gán cho các biến đã có trong môi trường toàn cầu hoặc tạo một biến trong môi trường toàn cầu ngay cả khi bạn đang ở trong một hàm. Tuy nhiên, nó không hoàn toàn đơn giản như vậy. Những gì nó làm là kiểm tra môi trường cha cho một biến có tên quan tâm. Nếu nó không tìm thấy nó trong môi trường cha mẹ của bạn, nó sẽ chuyển đến cha mẹ của môi trường cha mẹ (tại thời điểm hàm được tạo) và nhìn vào đó. Nó tiếp tục hướng lên môi trường toàn cầu và nếu không tìm thấy trong môi trường toàn cầu, nó sẽ gán biến trong môi trường toàn cầu.
Điều này có thể minh họa những gì đang xảy ra.
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"
Lần đầu tiên chúng tôi in thanh mà chúng tôi chưa gọi foo
nên nó vẫn mang tính toàn cầu - điều này có ý nghĩa. Lần thứ hai chúng tôi in nó bên trong foo
trước khi gọi baz
để giá trị "trong foo" có ý nghĩa. Sau đây là nơi chúng ta thấy những gì <<-
đang thực sự làm. Giá trị tiếp theo được in là "in baz - before << -" mặc dù câu lệnh in xuất hiện sau <<-
. Điều này là do <<-
không nhìn vào môi trường hiện tại (trừ khi bạn ở trong môi trường toàn cầu trong trường hợp đó <<-
hoạt động như thế nào <-
). Vì vậy, bên trong baz
giá trị của thanh vẫn là "in baz - trước << -". Khi chúng ta gọi baz
bản sao của thanh bên trong foo
được thay đổi thành "in baz" nhưng như chúng ta có thể thấy toàn cầu bar
là không thay đổi.bar
được định nghĩa bên trong foo
là trong môi trường phụ huynh khi chúng tôi tạo ra baz
vì vậy đây là bản sao đầu tiên của bar
mà <<-
nhìn thấy và do đó sao chép nó gán cho. Vì vậy, <<-
không chỉ trực tiếp giao cho môi trường toàn cầu.
<<-
là khó khăn và tôi không khuyên bạn nên sử dụng nó nếu bạn có thể tránh nó. Nếu bạn thực sự muốn gán cho môi trường toàn cầu, bạn có thể sử dụng hàm gán và nói rõ rằng bạn muốn gán toàn cục.
Bây giờ tôi thay đổi <<-
câu lệnh gán và chúng ta có thể thấy tác dụng nào có:
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"
Vì vậy, cả hai lần chúng tôi in thanh bên trong foo
giá trị là "trong foo" ngay cả sau khi gọi baz
. Điều này là do assign
thậm chí không bao giờ xem xét bản sao bar
bên trong của foo bởi vì chúng tôi đã nói với nó chính xác nơi để tìm. Tuy nhiên, lần này giá trị của thanh trong môi trường toàn cầu đã thay đổi vì chúng tôi được chỉ định rõ ràng ở đó.
Bây giờ bạn cũng đã hỏi về việc tạo các biến cục bộ và bạn có thể thực hiện điều đó khá dễ dàng mà không cần tạo hàm ... Chúng ta chỉ cần sử dụng local
hàm.
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
...