在 R 中提取函数参数值的奇怪行为
Strange behavior extracting function arguments values in R
如何提取列表中的所有函数参数值?
我试过这个:
x <- 1; y <- 2; z <- 3
testFunc <- function(a, b, c){
args <- as.list(sys.call())[-1]
evaluatedArgs <- lapply(args, function(x) eval(x))
evaluatedArgs
}
str(testFunc(x,y,z))
List of 3
$ : symbol x
$ : num 2
$ : num 3
如您所见,如果 function(x)
内部的 x
和外部变量 x
存在奇怪的冲突,这会阻止对第一个参数的评估。
如何解决这个冲突?对我来说,这是一个奇怪的范围组合。
更新
现在我知道lapply(args, function(x) eval(x))
解决了问题,但我想了解为什么会发生冲突。
您的 args
变量是 "symbol" 的 "list" 并在您的匿名 lapply
函数中作为参数传递。所以,隔离问题,你实际上是在做:
x = 10; y = 20
(function(x) eval(x))(substitute(x))
#x
(function(x) eval(x))(substitute(y))
#[1] 20
eval
在其 parent.frame
中评估其参数,这里是上述函数的 environment()
。该环境包含函数的参数和传递的值:
(function(x) as.list(environment()))(substitute(x))
#$x
#x
#
(function(x) as.list(environment()))(substitute(y))
#$x
#y
在第一种情况下,eval
需要评估 参数 "x" 转换为评估 符号 "x"。要评估 符号 "x",它首先需要找到它,并且它在自己的环境中找到它,因为它是它的参数。找到的 "x" 包含 符号 "x" 并返回。在第二种情况下,评估 argument "x" 转换为评估不在其环境中的 symbol "y" ,但在其包含值“20”的父环境中找到并返回。
具体来说,我们需要将评估环境传递给 eval
:
(function(x) { e = environment(); eval(x, parent.env(e)) })(substitute(x))
#[1] 10
(function(x) { e = environment(); eval(x, parent.env(e)) })(substitute(y))
#[1] 20
这里,参数被评估为函数当前环境的父环境(即 - 在这种情况下 - .GlobalEnv
)。因此,修改您的函数以正确搜索:
x = 1; y = 2; z = 3
testFunc = function(a, b, c)
{
args = as.list(sys.call())[-1]
e = environment()
lapply(args, function(x) eval(x, e))
}
我们得到:
str(testFunc(x,y,z))
#List of 3
# $ : num 1
# $ : num 2
# $ : num 3
如何提取列表中的所有函数参数值?
我试过这个:
x <- 1; y <- 2; z <- 3
testFunc <- function(a, b, c){
args <- as.list(sys.call())[-1]
evaluatedArgs <- lapply(args, function(x) eval(x))
evaluatedArgs
}
str(testFunc(x,y,z))
List of 3
$ : symbol x
$ : num 2
$ : num 3
如您所见,如果 function(x)
内部的 x
和外部变量 x
存在奇怪的冲突,这会阻止对第一个参数的评估。
如何解决这个冲突?对我来说,这是一个奇怪的范围组合。
更新
现在我知道lapply(args, function(x) eval(x))
解决了问题,但我想了解为什么会发生冲突。
您的 args
变量是 "symbol" 的 "list" 并在您的匿名 lapply
函数中作为参数传递。所以,隔离问题,你实际上是在做:
x = 10; y = 20
(function(x) eval(x))(substitute(x))
#x
(function(x) eval(x))(substitute(y))
#[1] 20
eval
在其 parent.frame
中评估其参数,这里是上述函数的 environment()
。该环境包含函数的参数和传递的值:
(function(x) as.list(environment()))(substitute(x))
#$x
#x
#
(function(x) as.list(environment()))(substitute(y))
#$x
#y
在第一种情况下,eval
需要评估 参数 "x" 转换为评估 符号 "x"。要评估 符号 "x",它首先需要找到它,并且它在自己的环境中找到它,因为它是它的参数。找到的 "x" 包含 符号 "x" 并返回。在第二种情况下,评估 argument "x" 转换为评估不在其环境中的 symbol "y" ,但在其包含值“20”的父环境中找到并返回。
具体来说,我们需要将评估环境传递给 eval
:
(function(x) { e = environment(); eval(x, parent.env(e)) })(substitute(x))
#[1] 10
(function(x) { e = environment(); eval(x, parent.env(e)) })(substitute(y))
#[1] 20
这里,参数被评估为函数当前环境的父环境(即 - 在这种情况下 - .GlobalEnv
)。因此,修改您的函数以正确搜索:
x = 1; y = 2; z = 3
testFunc = function(a, b, c)
{
args = as.list(sys.call())[-1]
e = environment()
lapply(args, function(x) eval(x, e))
}
我们得到:
str(testFunc(x,y,z))
#List of 3
# $ : num 1
# $ : num 2
# $ : num 3