2009-07-23 41 views
30

Tôi thường viết các hàm cần xem các đối tượng khác trong môi trường của mình. Ví dụ:Chức năng viết trong R, giữ phạm vi ghi nhớ

> a <- 3 
> b <- 3 
> x <- 1:5 
> fn1 <- function(x,a,b) a+b+x 
> fn2 <- function(x) a+b+x 
> fn1(x,a,b) 
[1] 7 8 9 10 11 
> fn2(x) 
[1] 7 8 9 10 11 

Như mong đợi, cả hai chức năng này giống hệt nhau vì fn2 có thể "xem" a và b khi thực thi. Nhưng bất cứ khi nào tôi bắt đầu tận dụng điều này, trong vòng khoảng 30 phút, tôi sẽ kết thúc cuộc gọi mà không có một trong các biến cần thiết (ví dụ: a hoặc b). Nếu tôi không tận dụng điều này, thì tôi cảm thấy như tôi đang đi qua những đồ vật không cần thiết.

Tốt hơn là phải rõ ràng về chức năng yêu cầu? Hoặc điều này có được thực hiện thông qua nhận xét nội tuyến hoặc tài liệu khác của hàm không? Có cách nào tốt hơn?

Trả lời

36

Nếu tôi biết rằng tôi sẽ cần một hàm parametrized bởi một số giá trị và kêu gọi nhiều lần, tôi tránh globals bằng cách sử dụng một kết thúc:

make.fn2 <- function(a, b) { 
    fn2 <- function(x) { 
     return(x + a + b) 
    } 
    return(fn2) 
} 

a <- 2; b <- 3 
fn2.1 <- make.fn2(a, b) 
fn2.1(3) # 8 
fn2.1(4) # 9 

a <- 4 
fn2.2 <- make.fn2(a, b) 
fn2.2(3) # 10 
fn2.1(3) # 8 

này gọn gàng tránh tham chiếu các biến toàn cầu, thay vì sử dụng kèm theo môi trường của hàm cho a và b. Sửa đổi các hình cầu a và b không dẫn đến các tác dụng phụ không mong muốn khi các cá thể fn2 được gọi.

3

Sự cố có xảy ra khi bạn chỉ sử dụng biến toàn cầu trong một hàm hoặc khi bạn cố gán biến? Nếu đó là sau này tôi nghi ngờ đó là bởi vì bạn không sử dụng <<- như một nhiệm vụ trong chức năng. Và trong khi sử dụng <<- dường như là mặt tối 1, nó có thể hoạt động rất tốt cho mục đích của bạn. Nếu nó là trước đây, hàm này có thể che dấu biến toàn cầu.

Đặt tên cho các biến toàn cầu theo cách mà chúng sẽ khó che dấu chúng cục bộ có thể hữu ích. ví dụ: global.pimultiples <- 1:4*pi

8

Có lý do khiến một số ngôn ngữ không cho phép biến toàn cầu: chúng có thể dễ dàng dẫn đến mã bị hỏng.

Quy tắc phạm vi trong R cho phép bạn viết mã theo kiểu thời trang lười biếng - cho phép các hàm sử dụng biến trong môi trường khác có thể giúp bạn nhập một số thao tác.

Tuy nhiên, nếu bạn làm bất kỳ điều gì phức tạp, thì tôi khuyên bạn nên chuyển một hàm tất cả các biến mà nó cần (hoặc ít nhất, có một số kiểm tra kỹ lưỡng tại chỗ để có dự phòng trong trường hợp biến không tồn tại).

Trong ví dụ trên:

Cách tốt nhất là sử dụng fn1.

Ngoài ra, hãy thử một cái gì đó giống như

fn3 <- function(x) 
    { 
     if(!exists("a", envir=.GlobalEnv)) 
     { 
     warning("Variable 'a' does not exist in the global environment") 
     a <- 1 
     } 

     if(!exists("b", envir=.GlobalEnv)) 
     { 
     warning("Variable 'b' does not exist in the global environment") 
     b <- 2 
     } 

     x + a + b 
    } 
0

Sử dụng các biến toàn cục được chung nản trong hầu hết các ngôn ngữ, và R là không có ngoại lệ. Chức năng rất ngắn thường sử dụng tên biến ngắn và chung chung, có thể được phổ biến trong môi trường toàn cầu. An toàn nhất là a) bao gồm tất cả các biến trong định nghĩa hàm b) không để gán giá trị mặc định. Ví dụ: viết hàm f = (a, b), thay vì hàm f = (a = 0, b = NA).

Các vấn đề liên quan