2011-12-26 45 views
10

Tôi đã đọc tài liệu cho parent.env() và có vẻ khá đơn giản - nó trả về môi trường kèm theo. Tuy nhiên, nếu tôi sử dụng parent.env() để đi bộ chuỗi các môi trường kèm theo, tôi thấy một cái gì đó mà tôi không thể giải thích. Thứ nhất, mã (lấy từ "R trong một nutshell")parent.env (x) nhầm lẫn

library(PerformanceAnalytics) 
x = environment(chart.RelativePerformance) 
while (environmentName(x) != environmentName(emptyenv())) 
{ 
    print(environmentName(parent.env(x))) 
    x <- parent.env(x) 
} 

Và kết quả:

[1] "imports:PerformanceAnalytics" 
[1] "base" 
[1] "R_GlobalEnv" 
[1] "package:PerformanceAnalytics" 
[1] "package:xts" 
[1] "package:zoo" 
[1] "tools:rstudio" 
[1] "package:stats" 
[1] "package:graphics" 
[1] "package:utils" 
[1] "package:datasets" 
[1] "package:grDevices" 
[1] "package:roxygen2" 
[1] "package:digest" 
[1] "package:methods" 
[1] "Autoloads" 
[1] "base" 
[1] "R_EmptyEnv" 

Làm thế nào chúng ta có thể giải thích các "cơ sở" ở đầu và "cơ sở" ở đáy? Ngoài ra, làm cách nào chúng tôi có thể giải thích "package: PerformanceAnalytics" và "import: PerformanceAnalytics"? Tất cả mọi thứ có vẻ phù hợp mà không có hai dòng đầu tiên. Đó là, biểu đồ hàm.RelativePerformance nằm trong gói: môi trường PerformanceAnalytics được tạo bởi xts, được tạo bởi sở thú, ... tất cả các con đường lên (hoặc xuống) đến cơ sở và môi trường trống.

Ngoài ra, tài liệu không phải là siêu rõ ràng về điều này - là "môi trường kèm theo" môi trường trong đó môi trường khác được tạo ra và do đó đi bộ parent.env() cho thấy một chuỗi "sáng tạo"?

Sửa

Shameless plug: Tôi đã viết một blog post giải thích môi trường, parent.env(), thùng, namespace/gói vv với sơ đồ trực quan.

+0

nhờ tất cả những ai đã đóng góp về các vấn đề này. Rất khó để chọn câu trả lời vì tất cả các bài đăng đều tuyệt vời – SFun28

Trả lời

3

Một vài mục đầu tiên trong kết quả của bạn cung cấp bằng chứng về các quy tắc R sử dụng để tìm kiếm các biến được sử dụng trong các hàm trong gói có không gian tên. Từ R-ext manual:

Không gian tên kiểm soát chiến lược tìm kiếm cho các biến được các hàm sử dụng trong gói. Nếu không tìm thấy cục bộ, R tìm kiếm không gian tên gói trước, sau đó nhập khẩu, sau đó là không gian tên cơ sở và sau đó là đường dẫn tìm kiếm thông thường.

Lập chỉ là một chút, có một cái nhìn tại một vài dòng đầu tiên của chart.RelativePerformance:

head(body(chart.RelativePerformance), 5) 
# { 
#  Ra = checkData(Ra) 
#  Rb = checkData(Rb) 
#  columns.a = ncol(Ra) 
#  columns.b = ncol(Rb) 
# } 

Khi có cuộc gọi đến chart.RelativePerformance đang được đánh giá, mỗi người trong số những biểu tượng --- liệu checkData trên đường dây 1, hoặc ncol trên dòng 3 --- cần được tìm thấy ở đâu đó trên đường dẫn tìm kiếm. Dưới đây là một vài môi trường kèm theo đầu tiên được chọn:

  • Trước hết là namespace:PerformanceAnalytics. checkData được tìm thấy ở đó, nhưng ncol thì không.

  • Điểm dừng tiếp theo (và vị trí đầu tiên được liệt kê trong kết quả của bạn) là imports:PerformanceAnalytics. Đây là danh sách các hàm được chỉ định như là các tệp nhập trong tệp NAMESPACE của gói. ncol cũng không tìm thấy ở đây.

  • Không gian tên base môi trường (nơi ncol sẽ được tìm thấy) là điểm dừng cuối cùng trước khi tiếp tục đến đường dẫn tìm kiếm thông thường. Hầu như mọi chức năng R sẽ sử dụng một số chức năng base, do đó, dừng này đảm bảo rằng không có chức năng nào có thể bị phá vỡ bởi các đối tượng trong môi trường toàn cầu hoặc trong các gói khác.(Nhà thiết kế R có thể đã để lại nó để đóng gói các tác giả để nhập khẩu một cách rõ ràng môi trường base trong NAMESPACE tập tin của họ, nhưng thêm đường chuyền mặc định này thông qua base dường như giống như quyết định thiết kế tốt hơn.)

+0

Josh - nhưng tôi đang gọi parent.env() là môi trường kèm theo. Tôi có hiểu lầm những gì parent.env() là nghĩa vụ phải làm gì? Theo chuỗi trên, môi trường gobal là một "cha mẹ" hoặc "bao quanh" cơ sở và xuống các cơ sở dòng bao quanh "Autoloads" để cơ sở có hiệu lực bao quanh cơ sở! Vì vậy, chúng ta đang nói rằng parent.env() thực sự không phải là môi trường kèm theo cho đến khi bạn đến môi trường toàn cầu? – SFun28

+0

@ SFun28 Sự hiểu biết của tôi (không hoàn hảo) là "cha mẹ-con" có thể là một ẩn dụ gây hiểu lầm cho env. Một env kèm theo là nhiều hơn một con trỏ của nơi R trông bên cạnh một mối quan hệ ngăn chặn nghiêm ngặt. Vì vậy, bạn có thể có thể xây dựng tất cả các loại chuỗi không trực quan của vòng lặp của env trở lại vào chính chúng. – joran

+0

Ồ - Tôi nghĩ tôi thấy mối quan tâm của bạn. Như G. Grothendieck & kohske nhấn mạnh, 'base' đầu tiên được tìm kiếm được gọi là' namespace: base', để làm cho cơ chế tìm kiếm này có thể. Nội dung của nó giống hệt với 'package: base', như được hiển thị bằng cách cố gắng' giống hệt nhau (ls (baseenv()), ls (.BaseNamespaceEnv)) ' –

3

Thứ hai base.BaseNamespaceEnv, trong khi giây đến cuối cùng là basebaseenv(). Đây không phải là khác nhau (có lẽ là cha mẹ của nó). Phụ huynh của .BaseNamespaceEnv.GlobalEnv, trong khi số của baseenv()emptyenv().

Trong gói, như @Josh nói, R tìm kiếm không gian tên của gói, sau đó nhập, sau đó là cơ sở (tức là, BaseNamespaceEnv).

bạn có thể tìm thấy điều này bằng cách, ví dụ .:

> library(zoo) 

> packageDescription("zoo") 
Package: zoo 

# ... snip ... 

Imports: stats, utils, graphics, grDevices, lattice (>= 0.18-1) 

# ... snip ... 

> x <- environment(zoo) 

> x 
<environment: namespace:zoo> 

> ls(x) # objects in zoo 
    [1] "-.yearmon"    "-.yearqtr"    "[.yearmon"    
    [4] "[.yearqtr"    "[.zoo"     "[<-.zoo"     
# ... snip ... 

> y <- parent.env(x) 
> y # namespace of imported packages 
<environment: 0x116e37468> 
attr(,"name") 
[1] "imports:zoo" 

> ls(y) # objects in the imported packages 

    [1] "?"          "abline"        
    [3] "acf"         "acf2AR"        
# ... snip ... 
+0

kohske - ah! Tôi đã không nhận ra rằng đây là hai môi trường khác nhau. Vì vậy, thật sự mỗi môi trường in là một môi trường độc đáo? Tôi bắt đầu thấy sự nhầm lẫn giữa môi trường "không gian tên", "nhập" và "gói". Không được hiển thị là môi trường của x đầu tiên là "không gian tên: PerformanceAnalytics".Bạn có thể làm rõ sự khác biệt giữa các môi trường này, khi chúng được tải và cách chúng có liên quan với nhau không? – SFun28

+0

cảm ơn vì đã xây dựng câu trả lời của bạn, nó đã giúp ích rất nhiều! – SFun28

5

1) Về cách base có thể có hai lần (cho rằng môi trường tạo thành một cây), nó lỗi của environmentName chức năng. Trên thực tế, lần xuất hiện đầu tiên là .BaseNamespaceEnv và lần xuất hiện thứ hai là baseenv().

> identical(baseenv(), .BaseNamespaceEnv) 
[1] FALSE 

2) Về imports:PerformanceAnalytics đó là một môi trường đặc biệt mà R thiết lập để giữ hàng nhập khẩu nêu trong không gian tên hoặc DESCRIPTION hồ sơ của gói sao cho các đối tượng trong nó đang gặp phải trước khi bất cứ điều gì khác.

Hãy thử chạy tính năng này để rõ ràng. Các str(p) và sau if tuyên bố sẽ đưa ra một ý tưởng tốt hơn về những gì p là:

library(PerformanceAnalytics) 
x <- environment(chart.RelativePerformance) 
str(x) 
while (environmentName(x) != environmentName(emptyenv())) { 
    p <- parent.env(x) 
    cat("------------------------------\n") 
    str(p) 
    if (identical(p, .BaseNamespaceEnv)) cat("Same as .BaseNamespaceEnv\n") 
    if (identical(p, baseenv())) cat("Same as baseenv()\n") 
    x <- p 
} 
+0

Thật tuyệt vời! Các mối quan hệ parent.env là dễ dàng hơn nhiều để xem với mã này. Tôi tò mò, lợi thế của việc nhập khẩu trong một gói là gì? Tôi đã tạo gói của riêng mình nhưng không sử dụng hàng nhập khẩu. Nó chỉ đơn giản là để tìm các biểu tượng nhanh hơn hoặc đưa ra một biểu tượng ưu tiên cao hơn so với cùng một biểu tượng trong cơ sở? – SFun28

+0

Bằng cách sử dụng 'import', bạn có thể làm cho các đối tượng trong các gói nhập ẩn với người dùng. Nếu gói A của bạn nhập B, bạn có thể sử dụng các đối tượng của B từ gói của bạn. Nhưng người dùng không thể sử dụng các đối tượng của B ngay cả sau khi tải A. – kohske

+0

bằng cách này, đây là một hàm tiện ích/trợ giúp tuyệt vời (tức là gói mã của bạn trong một hàm có tên là SearchPath (x)). Có vẻ như R cung cấp một hàm search() và searchpaths(), nhưng không cho phép chúng ta chỉ định một điểm khởi đầu khác với globalenv – SFun28