2017-11-25 150 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

相关问题