承诺已经在评估中:递归默认参数引用或早期问题?

Tim*_*Tim 132 r

这是我的R代码.功能定义为:

f <- function(x, T) {
  10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80
}

g <- function(x, T, f=f) {
  exp(-f(x) / T)
}

test <- function(g=g, T=1) { 
  g(1, T)
}
Run Code Online (Sandbox Code Playgroud)

运行错误是:

> test()test()中的
错误:
承诺已经在评估中:递归默认参数引用或早期问题?

如果我替代的定义f在的g,那么错误消失.

我想知道错误是什么?如何纠正它,如果没有替代的定义f在的g?谢谢!


更新:

谢谢!两个问题:

(1)如果函数test进一步论证f,你会添加类似的东西test <- function(g.=g, T=1, f..=f){ g.(1,T, f.=f..) }吗?在递归更多的情况下,添加更多是一个好的和安全的做法.

(2)if f是非函数参数,例如,g <- function(x, T, f=f){ exp(-f*x/T) }并且test <- function(g.=g, T=1, f=f){ g.(1,T, f=f.) },对于正式和实际的非功能性参数使用相同的名称是一个好的和安全的做法,还是会引起一些潜在的麻烦?

G. *_*eck 142

形式的正式论证x=x导致了这一点.消除它们出现的两个实例,我们得到:

f <- function(x, T) {
   10 * sin(0.3 * x) * sin(1.3 * x^2) + 0.001 * x^3 + 0.2 * x + 80 
}

g <- function(x, T, f. = f) {  ## 1. note f.
   exp(-f.(x)/T) 
}

test<- function(g. = g, T = 1) {  ## 2. note g.
   g.(1,T) 
}

test()
## [1] 8.560335e-37
Run Code Online (Sandbox Code Playgroud)

  • 还有其他方法吗?我在函数链(大约5个级别)中深入传递了一些参数,这个解决方案可能变得"麻烦".:) (16认同)
  • @RomanLuštrik 如果您向下传递参数并且可以安全地忽略其中一些参数,那么请考虑使用省略号 `...` 或列表将参数向下传递到函数链。它比预先定义一切要灵活得多(无论好坏)。您可能最终需要添加一些检查以确保省略号(或列表)中的原始参数是合理的。 (3认同)
  • 谢谢!两个问题(1)如果函数*test*进一步采用*f*的参数,你会添加类似*test < - function(g.= g,T = 1,f .. = f){g.(1) ,T,f.= f ..)}*?在递归更多的情况下,添加更多*.*是一种安全的好方法吗?(2)如果*f*是非函数参数,例如*g < - function(x,T,f = f){exp(-f*x/T)}*和*test < - function(g .= g,T = 1,f = f){g.(1,T,f = f.)}*,对正式和实际的非功能性参数使用相同的名称是一种良好且安全的做法,或者可能是造成一些潜在的麻烦? (2认同)
  • 这里的另一种选择是显式地尝试在父框架中查找参数,从而绕过主动承诺的意外强制-例如,“ get(“ f”,envir = parent.frame())”。 (2认同)
  • 唯一的要求是您不要在左侧和右侧使用相同的名称。除此之外,它只是风格。 (2认同)

rrr*_*rrr 12

如前所述,问题来自于将函数参数定义为自身。但是,我想解释一下为什么这是一个问题,因为理解使我找到了一种更简单(对我而言)避免问题的方法:只需在调用中指定参数而不是定义。

这不起作用:

x = 4
my.function <- function(x = x){} 
my.function() # recursive error!
Run Code Online (Sandbox Code Playgroud)

但这确实有效:

x = 4
my.function <- function(x){} 
my.function(x = x) # works fine!
Run Code Online (Sandbox Code Playgroud)

函数参数存在于它们自己的本地环境中。

R 首先在本地环境中查找变量,然后在全局环境中查找。这就像函数内部的变量如何与全局环境中的变量具有相同的名称,而 R 将使用本地定义。

让函数参数定义形成它们自己的本地环境,这就是为什么您可以基于其他参数值拥有默认参数值的原因,例如

my.function <- function(x, two.x = 2 * x){}
Run Code Online (Sandbox Code Playgroud)

所以这就是为什么你不能定义一个函数,my.function <- function(x = x){}但是你可以使用my.function(x = x). 当您定义函数时,R 会感到困惑,因为它发现参数x =是 的本地值x,但是当您调用函数时,R 会在您调用x = 4的本地环境中找到。

因此,除了通过更改参数名称或显式指定其他答案中提到的环境来修复错误之外,您还可以仅x=x在调用函数时而不是在定义函数时指定。对我来说,x=x在调用中指定是最好的解决方案,因为它不涉及额外的语法或积累越来越多的变量名称。


xm1*_*xm1 6

如果指定参数评估上下文,则可以避免出现同名问题:

f <- function(x) {
  10 * sin(0.3 * x) * sin(1.3 * x ^ 2) + 0.001 * x ^ 3 + 0.2 * x + 80
}
g <- function(x, t=1, f=parent.frame()$f) {
  exp(-f(x) / t)
}
test <- function(g=parent.frame()$g, t=1) { 
  g(1,t)
}
test()
[1] 8.560335e-37
Run Code Online (Sandbox Code Playgroud)

  • 这是一个更好的方法,我认为指定环境更加清晰 (2认同)