【问题标题】:substitute does not work as expected替代品没有按预期工作
【发布时间】:2017-08-14 07:10:22
【问题描述】:

根据文档

通过检查解析树的每个组件来进行替换,如下所示:如果它不是 env 中的绑定符号,则它是不变的。如果它是一个 Promise 对象,即函数的正式参数或使用delayedAssign() 显式创建,则promise 的表达式槽将替换符号。如果是普通变量,则替换它的值,除非 env 是 .GlobalEnv 在这种情况下符号保持不变。

所以我做了一些实验

a = 10

# first
f1 = function(x){
  substitute(x)
  }
f1(a)
# [1] a


# second
f1 = function(x){
  x
  substitute(x)
  }
f1(a)
# [1] a

# third
f1 = function(x){
  force(x)
  substitute(x)
  }
f1(a)
# [1] a

# fourth
f1 = function(x){
  x = x
  substitute(x)
  }
f1(a)
# [1] 10

在第二个和第三个实验中,我认为 x 不再是一个承诺,所以 substitute 应该返回 10 而不是 a。但它仍然返回a。为什么?

【问题讨论】:

  • x 和 force(x) 在第二种和第三种情况下没有分配。因此,substitute(x) 在两种情况下都作为x 的原始值返回,即a
  • 如果分配了force(x),例如f1 <-function(x){tmp <- force(x); substitute(tmp)} 然后f1(a) 将返回值10
  • 来自语言定义:“在访问该参数之前,没有与承诺相关联的值。访问参数时,存储的表达式在存储的环境中进行评估,并返回结果。结果也由 promise 保存。替代函数将提取表达式槽的内容。这允许程序员访问与 promise 关联的值或表达式。即使它的表达式已经被评估,一个 Promise 仍然是一个 Promise。
  • @AdamQuek 我同意这与是否分配x 有关。但是substitute 是如何检测到x 被分配的呢?如果您使用ls.str(environment()),您可以看到x 已经绑定到10。
  • @Roland 我明白了。因此,除非 promise x 被局部变量“x”覆盖,否则无论它是否被评估,它都将保持一个 promise。

标签: r


【解决方案1】:

来自language definition:

在访问该参数之前,没有任何值与 承诺。访问参数时,存储的表达式为 在存储环境中求值,并返回结果。这 结果也被承诺保存。替代功能将 提取表达式槽的内容。这允许程序员 访问与 承诺。

即使它的表达式已经被评估,一个承诺仍然是一个承诺。你可以看到 pryr 包发生了什么:

library(pryr)
f=function(x){
  print(promise_info(x))
  force(x)
  promise_info(x)
}

a <- 10
f(a)

#$code
#a
#
#$env
#<environment: R_GlobalEnv>
#
#$evaled
#[1] FALSE
#
#$value
#NULL
############################
#$code
#a
#
#$env
#NULL
#
#$evaled
#[1] TRUE
#
#$value
#[1] 10

显然,为符号分配一个新值会用该值替换承诺。这就是您上一个函数中发生的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-01
    • 2015-07-10
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 2021-10-19
    • 2020-03-18
    相关资源
    最近更新 更多