R: Promise 找不到对象
R: Promise cannot find object
我知道您可以在 R 中编写一个函数,其中参数的默认值是使用同一函数的另一个参数。
foo <- function(a, b = length(a)) {
b
}
foo(a = c(1, 2))
[1] 2
但是,一旦我在实际函数调用中使用相同的参数,我就会收到错误消息:
foo(a = c(1, 2), b = length(a))
Error in foo(a = c(1, 2), b = length(a)) : object 'a' not found
我认为 b = length(a)
的承诺应该在函数内部进行评估,其中 a
是已知的,但显然这没有发生。谁能解释一下问题出在哪里以及我该怎么做
foo(a = c(1, 2), b = length(a))
工作?
当键入 foo(a = c(1, 2), b = length(a))
时,a
必须来自调用环境,而不是函数环境。您需要使用:
x <- 1:2
foo(a = x, b = length(x))
或者使用函数参数:
foo <- function(a, fun = length) { fun(a) }
引用Hadley:
More technically, an unevaluated argument is called a promise, or
(less commonly) a thunk. A promise is made up of two parts:
The expression which gives rise to the delayed computation. (It can be accessed with substitute(). See non-standard evaluation for
more details.)
The environment where the expression was created and where it should be evaluated.
你说得对,参数是承诺,只有在需要时才会评估。但是,promise 包括创建它的环境,在本例中是全局环境。
我的理解是,当您显式地为函数提供参数时,默认行为是在给出参数的环境中评估所述参数, 而不是 函数执行环境(如 详情)。
有可能解决这个问题(你是否应该是另一回事)。您可以结合使用 substitute()
(捕获未评估的参数)和 eval()
来更改参数评估的环境。这里我们在 foo
中显式评估 b
的执行环境:
foo <- function(a, b = length(a)) {
eval(substitute(b), env = environment())
}
(由于 eval()
中的默认值,只写 eval(substitute(b))
就足够了。但有时明确一点会很好;像这样,更明显的是我们正在更改评估环境。)
现在以下不会抛出错误:
foo(a = c(1, 2), b = length(a))
#> [1] 2
但是,如果你决定走这条路,你应该非常明确地记录在执行环境中评估 b
参数的函数。例如,当 a
同时出现在给出参数的环境和执行环境中时会发生什么?如果没有详细记录,这可能是意外行为(即使有详细记录,也是难以诊断错误的来源)。
a <- 1:10
foo(a = c(1, 2), b = length(a))
#> [1] 2
有关评估(和陷阱)的更多详细信息,您可以查看the Evaluation chapter in Advanced R。
由 reprex package (v0.2.0) 创建于 2018-07-05。
我知道您可以在 R 中编写一个函数,其中参数的默认值是使用同一函数的另一个参数。
foo <- function(a, b = length(a)) {
b
}
foo(a = c(1, 2))
[1] 2
但是,一旦我在实际函数调用中使用相同的参数,我就会收到错误消息:
foo(a = c(1, 2), b = length(a))
Error in foo(a = c(1, 2), b = length(a)) : object 'a' not found
我认为 b = length(a)
的承诺应该在函数内部进行评估,其中 a
是已知的,但显然这没有发生。谁能解释一下问题出在哪里以及我该怎么做
foo(a = c(1, 2), b = length(a))
工作?
当键入 foo(a = c(1, 2), b = length(a))
时,a
必须来自调用环境,而不是函数环境。您需要使用:
x <- 1:2
foo(a = x, b = length(x))
或者使用函数参数:
foo <- function(a, fun = length) { fun(a) }
引用Hadley:
More technically, an unevaluated argument is called a promise, or (less commonly) a thunk. A promise is made up of two parts:
The expression which gives rise to the delayed computation. (It can be accessed with substitute(). See non-standard evaluation for more details.)
The environment where the expression was created and where it should be evaluated.
你说得对,参数是承诺,只有在需要时才会评估。但是,promise 包括创建它的环境,在本例中是全局环境。
我的理解是,当您显式地为函数提供参数时,默认行为是在给出参数的环境中评估所述参数, 而不是 函数执行环境(如
有可能解决这个问题(你是否应该是另一回事)。您可以结合使用 substitute()
(捕获未评估的参数)和 eval()
来更改参数评估的环境。这里我们在 foo
中显式评估 b
的执行环境:
foo <- function(a, b = length(a)) {
eval(substitute(b), env = environment())
}
(由于 eval()
中的默认值,只写 eval(substitute(b))
就足够了。但有时明确一点会很好;像这样,更明显的是我们正在更改评估环境。)
现在以下不会抛出错误:
foo(a = c(1, 2), b = length(a))
#> [1] 2
但是,如果你决定走这条路,你应该非常明确地记录在执行环境中评估 b
参数的函数。例如,当 a
同时出现在给出参数的环境和执行环境中时会发生什么?如果没有详细记录,这可能是意外行为(即使有详细记录,也是难以诊断错误的来源)。
a <- 1:10
foo(a = c(1, 2), b = length(a))
#> [1] 2
有关评估(和陷阱)的更多详细信息,您可以查看the Evaluation chapter in Advanced R。
由 reprex package (v0.2.0) 创建于 2018-07-05。