【问题标题】:How can I tell if a function argument is given as an expression without evaluating it?如何判断函数参数是否作为表达式给出而不对其进行评估?
【发布时间】:2014-08-19 07:03:22
【问题描述】:

这是一个将表达式作为参数的简单函数。

f <- function(expr) {
  expr <- substitute(expr)
  eval(expr)
}

(实际上,我还需要在函数中稍微操作一下表达式,并可能在其他有意义的环境中评估表达式)

当我们调用时它工作正常

f(1+1)

通过直接提供未评估的参数。

但是,我需要 f 也可以像在外部提供明确定义的表达式时一样工作,例如,

q <- quote(1+1)
f(q)

f(expr) 需要避免替换 expr 并返回表达式的值。但是,上面的代码不起作用,因为它会生成表达式本身而不是 2。

所以问题是:如何判断一个参数是否作为表达式给出而不在当前环境中评估它?

【问题讨论】:

    标签: r expression eval


    【解决方案1】:

    也许您想检查是否传递了“名称”而不是“呼叫”

    f <- function(expr) {
        expr <- substitute(expr)
        if(is.name(expr)) {
            expr <- eval(expr, parent.frame())
        }
        eval(expr)
    }
    
    
    f(1+1)
    # [1] 2
    
    q<-quote(1+1)
    f(q)
    # [1] 2
    

    【讨论】:

    • 我喜欢这种更简洁的方法。 +1
    • 为什么我们不能这样做:f &lt;- function(expr) {expr &lt;- substitute(expr); eval(expr, parent.frame())}(排除 cmets 中的单行函数)?
    • @TylerRinker 该方法肯定会正确评估表达式,我做了额外的步骤,因为 OP 说他们可能想要修改表达式。这样,在 if 语句之后,您应该能够修改将要评估的代码。
    • 小窍门:你永远不应该在类中使用==,因为它可能会返回多个值(我认为当对象不是 S3 时它会令人困惑)。这里可以使用is.name
    • 如果您直接提供引用的对象,这也会失败。基本上,尝试让函数同时执行标准和非标准 eval 是一个坏主意。
    【解决方案2】:

    可能有更好的方法,但这里有一种方法:

    f <- function(expr) {
        mess <- suppressWarnings(try(expr, silent = TRUE))
        if (inherits(mess, "try-error")) {
            expr <- substitute(expr)
        }
    
        eval(expr)
    }
    
    f(1+1)
    ## [1] 2
    
    q <- quote(1+1)
    f(q)
    ## [1] 2
    

    此位将其扩展到字符向量:

    f <- function(expr) {
        mess <- suppressWarnings(try(expr, silent = TRUE))
        if (inherits(mess, "try-error")) {
            expr <- substitute(expr)
        }
    
        if (is.character(expr)) return(eval(parse(text=expr)))
        eval(expr)
    }
    
    f("1 + 1")
    ## [1] 2
    

    我建议从 Hadley 的 Advanced R 阅读这篇文章 HERE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多