【问题标题】:Getting the parse tree for a predefined function in R获取 R 中预定义函数的解析树
【发布时间】:2013-06-11 21:51:38
【问题描述】:

我觉得这是一个相当基本的问题,但我无法弄清楚。

如果我在 R 中定义了一个函数,我以后如何使用函数的名称来获取它的解析树。我不能只使用substitute,因为它只会返回其参数的解析树,在这种情况下只是函数名。

例如,

> f <- function(x){ x^2 }
> substitute(f)
f

我应该如何使用函数名访问函数的解析树?例如,如何在不明确写出整个函数的情况下获得 substitute(function(x){ x^2 }) 的值?

【问题讨论】:

    标签: r substitution parse-tree


    【解决方案1】:

    我不确定其中哪一个符合您的要求:

     eval(f)
    #function(x){ x^2 }
    
     identical(eval(f), get("f"))
    #[1] TRUE
     identical(eval(f), substitute( function(x){ x^2 })  )
    #[1] FALSE
    
     deparse(f)
    #[1] "function (x) " "{"             "    x^2"       "}"            
    
     body(f)
    #------
    {
        x^2
    }
    #---------
    
    eval(parse(text=deparse(f)))
    #---------
    function (x) 
    {
        x^2
    }
    #-----------
    
     parse(text=deparse(f))
    #--------
    expression(function (x) 
    {
        x^2
    })
    #--------
    
     get("f")
    # function(x){ x^2 }
    

    打印表示可能无法显示返回值的全部特征。

     class(substitute(function(x){ x^2 }) )
    #[1] "call"
     class( eval(f) ) 
    #[1] "function"
    

    【讨论】:

    • 我可能错过了 smth,但我认为这些表达式中的任何一个都无法实现 OP 想要的,即与substitute(function(x){ x^2 })相同的输出
    • 我已将接受的答案更改为您的答案。在对函数列表进行了更多尝试之后,parse(text = deparse(f))[[1]] 与使用完全写出的函数的 substitute 完全相同。
    【解决方案2】:

    函数substitute 可以替换绑定到环境的值。奇怪的是它的env 参数没有默认值,但它默认为评估环境。当评估环境是全局环境时,此行为似乎使其失败,但在其他情况下工作正常。

    这是一个例子:

    > a = new.env()
    > a$f = function(x){x^2}
    > substitute(f, a)
    function(x){x^2}
    > f = function(x){x^2}
    > environment()
    <environment: R_GlobalEnv>
    > substitute(f, environment())
    f
    > substitute(f, globalenv())
    f
    

    如图所示,当使用全局环境作为第二个参数时,功能会失败。

    进一步演示它使用a 可以正常工作,但不能使用全局环境:

    > evalq(substitute(f), a)
    function(x){x^2}
    > evalq(substitute(f), environment())
    f
    

    相当令人费解。

    【讨论】:

      【解决方案3】:

      显然这确实是substitute 的一些奇怪的怪癖,并提到了here

      /* do_substitute 有两个参数,一个表达式和一个 环境(可选)。表达式中的符号是 替换为在环境中找到的值。有 没有继承,所以只搜索提供的环境。如果不 environment 指定了替代品所在的环境 调用被使用。 如果指定的环境是 R_GlobalEnv 它是 由于历史原因,转换为 R_NilValue。 在替代()中, R_NilValue 表示不应进行替换,仅 提取承诺表达式。 do_substitute 的参数 不应该被评估。 */

      而且你已经找到了绕过它的方法:

      e = new.env()
      e$fn = f
      substitute(fn, e)
      

      【讨论】:

      • 实际上,经过进一步测试,这似乎不太奏效。 substitute(f, a) 的类型是闭包,而 'substitute(function(x){ x^2 })' 的类型是语言对象,特别是调用。区别非常重要,因为闭包不是子集,但调用是。您知道从闭包转换为调用的任何快速方法吗? as.call 将不起作用。
      • 好点,顺便说一句,我刚刚意识到as.list(f)substitute 所做的事情基本相同
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多