将表达式传递给函数中的curve()

Ben*_*ker 9 r

一位同事问我这个,我一直在努力.

假设我想定义一个函数,它将一个表达式(比如说x^2具体性)作为一个参数并将该参数传递给curve().

如果我想以简单的方式做到这一点,我就跑了

curve(x^2,from=0,to=3)
Run Code Online (Sandbox Code Playgroud)

它工作正常.

假设我尝试设置一个包装函数(假设除了绘制曲线之外,我还想在包装器中做其他事情):

f <- function(g) {
    curve(g,from=0,to=3)
}
Run Code Online (Sandbox Code Playgroud)

如果我传递一个函数,这是有效的:

f(function(x) x^2)
Run Code Online (Sandbox Code Playgroud)

如果我试图传递x^2,当R试图评估表达式时,它会失败:

f(x^2)
## Error in eval(expr, envir, enclos) (from #2) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)

我可以尝试通过substitute在函数内使用来阻止它:

f0 <- function(g) {
    str(substitute(g))
    curve(substitute(g),from=0,to=3)
}
f0(x^2)
## language x^2
## Error in curve(substitute(g), from = 0, to = 3) (from #3) : 
##  'expr' must be a function, or a call or an expression containing 'x'
Run Code Online (Sandbox Code Playgroud)

好吧,这表明也许我应该尝试

f <- function(g) {
    h <- as.expression(substitute(g))
    str(h)
    curve(as.expression(substitute(g)),from=0,to=3)
}
f(x^2)
##  expression(x^2)
## Error in curve(as.expression(substitute(g)), from = 0, to = 3) (from #4) : 
##  'expr' must be a function, or a call or an expression containing 'x'
Run Code Online (Sandbox Code Playgroud)

物有所值,

  • 这与curve(h,...)(" h找不到功能")不同
  • 如果as.call()被替换,它会以同样的方式失败as.expression()
  • curve() 在任何情况下都不适用于表达式:

curve(expression(x^2),from=0,to=1)
## Error in curve(expression(x^2), from = 0, to = 1) : 
##   'expr' did not evaluate to an object of length 'n'
Run Code Online (Sandbox Code Playgroud)

如果我尝试调试curve()以查看正在发生的事情,我们有:

sexpr <- substitute(expr)
...
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in% 
    all.vars(sexpr))) 
    stop(...)
Run Code Online (Sandbox Code Playgroud)

sexprsubstitute(g),未通过xname %in% all.vars(sexpr)测试......

关于如何处理这个的任何想法?

Ben*_*ker 6

我不是故意要问 - 然后回答,但我想出了一个更好的问题(我的答案) - 我突然想到我还没有尝试过eval. eval(curve(substitute(g),from=0,to=3))确实没有工作,但这样做:

f1 <- function(g) {
     eval(substitute(curve(g,from=0,to=3)))
}
f1(x^2)
Run Code Online (Sandbox Code Playgroud)

更新:@RichardScriven建议也do.call()可以工作 - 它确实有效!

f2 <- function(g) {
    do.call(curve,list(substitute(g),from=0,to=3))
}
f2(x^2)
Run Code Online (Sandbox Code Playgroud)

欢迎进一步解释!

  • 看起来这个功能只能用于交互式工作(顶层),因此解决方法需要构建完全相同的调用,就像交互式编写一样,_then_ evaluate. (2认同)