【问题标题】:Forcing a function definition to evaluate a symbol强制函数定义评估符号
【发布时间】:2012-08-07 12:18:32
【问题描述】:

考虑下面的例子:

> x=2
> myfun = function(y) x*y
> myfun(3)
[1] 6
> x=4
> myfun(3)
[1] 12

我将如何定义 myfun 以使其定义保持 x 的值,例如在定义时的值,而不是对 x 的引用? (即,第二次调用 myfun(3) 也产生 6 而不是 12)。

编辑:更改标题以删除不正确的术语。

【问题讨论】:

  • 这是可能的,但有点奇怪。你能解释一下你为什么要这样做吗?无论如何,您的标题具有误导性(或者可能是错误的)。您的函数正在环境链中查找value。此处未引用任何内容。
  • 我同意@Andrie 的观点,很难为此设想一个用例。也许你想要的是一个闭包?
  • 我的术语可能不正确。我所说的引用的意思是函数的主体包含“x”而不是 x 在定义 (2) 时所持有的值。我希望正文不包含“x”,即拍摄快照。为什么你觉得这很奇怪?
  • @AriB.Friedman Closures 绝对可以做到这一点。我可能会修改我的答案以反映这一点。
  • @mitchus 这有点奇怪,因为通常如果你想对变量值进行快照,你会在代码中这样做。

标签: r


【解决方案1】:

我不得不猜测一下你的目的是什么。也许您只需要使用默认值定义您的参数之一:

myfun <- function(y, x=2){
  x * y
}

然后使用它:

x <- 3

myfun(4)
[1] 8

myfun(x=4, 3)
[1] 12

myfun(x)
[1] 6

但也许你真的在描述一个闭包。

对象是具有功能的数据。闭包是一个带有数据的函数。

--- 约翰·D·库克

这是一个例子。首先定义一个记住快照的闭包:

newSnapshot <- function(x){
  xx <- x
  function(y) xx * y
}

然后使用它:

x <- 10
myfun <- newSnapshot(x)

myfun(4)
[1] 40

x <- 4
myfun(5)
[1] 50

【讨论】:

    【解决方案2】:

    昨天在 R-help 邮件列表上提出了几乎相同的问题。 请参阅关于 Nabble 的讨论,了解您可以执行此操作的各种方法。

    http://r.789695.n4.nabble.com/Force-evaluation-of-a-symbol-when-a-function-is-created-td4639350.html

    这里有三种方法(收集自 R-help 讨论):

    x <- 2
    
    f1 <- local({x.now <- x;function(y) x.now*y})
    f2 <- evalq(function(y)a*y,env=list(a=x))
    
    multiply_by_x <- function(x) {
        force(x)
        function(y) y*x
    }
    
    f3 <- multiply_by_x(x)
    

    有结果

    > f1(3)
    [1] 6
    > f2(3)
    [1] 6
    > f3(3)
    [1] 6
    
    > x <- 4
    > f1(3)
    [1] 6
    > f2(3)
    [1] 6
    > f3(3)
    [1] 6
    

    【讨论】:

    • 这正是我想要的。顺便说一句,同时我发现了第四种可能有点hacky的方法:body(myfun) = eval(expression(parse(text = paste(x, "*y"))))
    • 我建议您在考虑再次使用parse() 之前先查看require(fortunes); fortune(106)。 :-)
    • 不那么可怕:formals(myfun)$x=x
    【解决方案3】:

    一种方法是这样的:

    myfun <- function(x = 2) {
        function(y) {
            x * y
        }
    }
    

    基本上,我们编写一个函数,该函数返回一个执行我们想要的计算的函数。上面的x 默认设置为2,但您可以在调用myfun 时更改此设置。当我们调用myfun() 时,我们将返回的函数保存在foo 中,如下例所示:

    > foo <- myfun()
    

    现在,无论您在全局环境 foo() 中对 x 做什么,都将始终使用在调用该函数时在 myfun() 环境中定义的 x 的值。

    > foo(3)
    [1] 6
    > x <- 6
    > foo(3)
    [1] 6
    > x <- 4
    > foo(3)
    [1] 6
    

    这一切都有效,因为调用 myfun() 创建的函数的环境包含 x 并且 x 的值是 x,该值在定义函数时存在。

    > environment(foo)$x
    [1] 2
    

    【讨论】:

    • 感谢您的回复。问题是,在编写代码时,我不知道在定义 myfunx 的值(与我选择不当的示例所暗示的不同)。
    【解决方案4】:

    这是另一种关闭解决方案:

    myfun <- local({
      x <- 2
      list(
        f=function(y) {
          x*y
        },
        set.x=function(newx) {
          x <<- newx
        },
        get.x=function() {
          x
        }
      )
    })
    

    那么你可以如下使用它:

    > myfun$get.x()
    [1] 2
    > myfun$set.x(5)
    > myfun$get.x()
    [1] 5
    > myfun$f(3)
    [1] 15
    

    【讨论】:

      猜你喜欢
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-17
      • 2021-12-19
      • 2016-06-28
      • 1970-01-01
      相关资源
      最近更新 更多