2017-11-25 191 views
2

我首先定義了一個新變量x,然後創建了一個函數,它需要在其體內(不作爲參數)使用x。見下文爲什麼這個簡單的功能不起作用?

x <- c(1,2,3) 
f1 <- function() { 
    x^2 
} 

rm(x) 

f2 <- function() { 
    x <- c(1,2,3) 
    f1() 
} 

f(2) 
Error in f1() : object 'x' not found 

代碼當我除去x,並定義新的函數f2該第一限定x然後執行f1,它顯示對象未找到x

我只是想知道爲什麼這不起作用,我怎麼能克服這個問題。我不想x被稱爲f1中的參數。

請提供適當的標題,因爲我不知道這是什麼樣的問題。

+4

沿環境「鏈」('parent.env')搜索變量名稱。 'f2'內聲明的'x'不在任何父環境中,而在「兄弟」環境中。請閱讀http://adv-r.had.co.nz/Environments。html的基本知識來詳細瞭解這個問題 –

回答

4

簡而言之:你期待的動態範圍界定,但都是R的詞法範圍的受害者:

  • 動態作用域=一個命​​令的封閉環境中在運行時間期間

  • 詞法作用域=命令的包圍環境是在「編譯時間」

確定要理解查找來確定在當前和父級環境中,您的變量x的路徑請嘗試使用此代碼。

這表明,與xf2定義,因此它不能永遠不會被發現兩種功能不共享環境:

# list all parent environments of an environment to show the "search path" 
parents <- function(env) { 
    while (TRUE) { 
    name <- environmentName(env) 
    txt <- if (nzchar(name)) name else format(env) 
    cat(txt, "\n") 
    if (txt == "R_EmptyEnv") break 
    env <- parent.env(env) 
    } 
} 

x <- c(1,2,3) 
f1 <- function() { 
    print("f1:") 
    parents(environment()) 
    x^2 
} 

f1() # works 
# [1] "f1:" 
# <environment: 0x4ebb8b8> 
# R_GlobalEnv 
# ... 

rm(x) 

f2 <- function() { 
    print("f2:") 
    parents(environment()) 
    x <- c(1,2,3) 
    f1() 
} 

f2() # does not find "x" 
# [1] "f2:" 
# <environment: 0x47b2d18> 
# R_GlobalEnv 
# ... 
# [1] "f1:" 
# <environment: 0x4765828> 
# R_GlobalEnv 
# ... 

可能的解決方案:

  1. 聲明x在全球環境(由於缺乏封裝,編程風格不佳)

  2. 使用f結參數(這是什麼功能的製造)

  3. 使用閉包,如果x具有總是相同值的f1每次調用(不適合初學者)。請參閱@JohnColeman的其他答案...

我強烈建議使用2.(將x添加爲參數 - 爲什麼要避免這種情況?)。

+2

也有可能在'f2'中使用superassignment運算符'x << - c(1,2,3)'。我知道,這是令人不悅的。指出它的完整性。 – RHertel

6

你可以使用一個closure,使具有所需性能的f1

makeF <- function(){ 
    x <- c(1,2,3) 
    f1 <- function() { 
    x^2 
    } 
    f1 
} 

f1 <- makeF() 
f1() #returns 1 4 9 

有在全球範圍內沒有xf1還是知道的,因爲它是在規定的環境中x

相關問題