【问题标题】:How to pass an object from outside a R-function to the function's body?如何将对象从 R 函数外部传递到函数体?
【发布时间】:2021-12-22 23:55:32
【问题描述】:

我想将在函数外部定义的对象的内容传递给函数体。 举个例子,我的问题可能更容易理解:

a <- 'hello world'
foo <- function() print(a)
rm(a)
foo()

目前,这显然会引发错误,因为在调用foo() 时不再定义a

我想要的结果是我希望 foo 看起来像 function() print('hello world')

【问题讨论】:

标签: r function


【解决方案1】:

1) 本地 像这样使用local 捕获a。这会将a 的值固定为定义foo 时的值。请注意,a &lt;- a 右侧的 a 是已定义的 a,而左侧的 a 是一个新对象,也称为 a,它在 @987654330 中定义@。没有使用任何包。

a <- 'hello world'
foo <- local({
  a <- a
  function() print(a)
})

rm(a)
foo()
## [1] "hello world"

2) 替代 另一种替代方法是像这样将a 的值替代到foo 的主体中。这会将foo 中的a 修复为运行substitute 时的值。没有使用任何包。

foo <- function() print(a)

a <- 'hello world'
body(foo) <- do.call("substitute", list(body(foo), list(a = a)))

rm(a)
foo()
## [1] "hello world"

3) 生成 foo 的函数 另一种可能性是创建一个生成 foo 的函数。注意R使用惰性求值,所以我们需要使用force来保证afoogen运行时的值被使用;否则,它将延迟评估,直到 a 被删除,导致错误。这会将foo 中的a 修复为传递给foogen 的值。没有使用任何包。

foogen <- function(a) {
  force(a)
  function() print(a)
}

a <- 'hello world'
foo <- foogen(a)
rm(a)
foo()
## [1] "hello world"

4) proto proto 包可用于创建对象p,其中包含fooa

library(proto)

p <- proto(foo = function(.) print(a))

a <- 'hello world'
p$a <- a
rm(a)
p$foo()
## [1] "hello world"

【讨论】:

    【解决方案2】:

    这里不需要使用eval(parse(...)),也不需要使用外部包。使用evalparsegenerally not a good idea for a few different reasons,包括恶意用户利用它的乐趣。随着 R 在接受用户输入的网络应用中的使用越来越多,这一点变得越来越重要。

    在没有eval(parse(...)) 或任何外部依赖项的情况下,有几种方法可以在基本 R 中执行此操作。一种方法是拥有一个函数工厂:

    a <- 'hello world'
    foo_maker <- function(x) as.function(list(x = a, quote(print(x))))
    

    所以现在我们可以这样做了:

    foo <- foo_maker(a)
    rm(a)
    foo()
    #> [1] "hello world"
    

    【讨论】:

      【解决方案3】:

      刚刚发现如何使用whisker 包和eval(parse(...)) 解决问题:

      library(whisker)
      a <- 'hello world'
      foo <- eval(parse(text = whisker.render('function() print("{{b}}")', 
                                              data = list(b = a))))
      foo()
      rm(a)
      foo()
      

      【讨论】:

        猜你喜欢
        • 2017-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 2012-10-14
        • 2013-03-15
        • 1970-01-01
        • 2020-07-17
        相关资源
        最近更新 更多