4

当一个函数已经定义但还没有被调用时,没有默认值的形式是否存在?如果存在,它们是否存在于执行环境中,或者存在于函数定义所在的环境中,或者其他地方?

如果一个函数已定义但尚未调用,并且已为形式分配了默认值,那么该值是否存在?如果有,它存在于什么环境中?如果默认表达式的计算结果为常量,是否已将形式分配给该值,如果提供了值,则在调用函数时将其覆盖?如果不是,那么(固定)默认值位于定义时刻和函数调用时刻之间的环境中是什么?

在调用函数并将实际值或默认值分配给形式后,将其传递到主体中,并在必要时进行作用域和/或评估后,形式是否继续存在?如果是这样,那么它们存在于什么环境中?

4

1 回答 1

4

一旦函数的实例被调用加载到内存中,函数的形式作为对象存在于函数的环境中。在Advanced R中,Hadley Wickham 将此环境称为执行环境。可以通过 访问对象的内存位置pryr::address()

作为示例,我将使用我之前编写的代码的修改版本来说明coursera.orgmakeVector()上Johns Hopkins R 编程课程的第二个编程作业中函数中的内存位置。

makeVector <- function(x = 200) {
     library(pryr)
     message(paste("Address of x argument is:",address(x)))
     message(paste("Number of references to x is:",refs(x)))
     m <- NULL
     set <- function(y) {
          x <<- y
          message(paste("set() address of x is:",address(x)))
          message(paste("Number of references to x is:",refs(x)))
          m <<- NULL
     }
     get <- function() x
     setmean <- function(mean) m <<- mean
     getmean <- function() m
     list(set = set, get = get,
          setmean = setmean,
          getmean = getmean)
}

如上所述,makeVector()是一个 S3 对象,这意味着我们可以通过 getter 和 setter(也称为mutator 方法)访问其环境中的对象。

我们可以将对象的一个​​实例加载到内存中,并使用以下代码makeVector()查询其地址和值。x

makeVector()$get()

...结果:

> makeVector()$get()
Address of x argument is: 0x1103df4e0
Number of references to x is: 0
[1] 200
> 

正如我们从输出中看到的,x确实有一个内存位置,但没有其他对象包含对它的引用。此外,x将其设置为长度为 1 且值为 200 的向量的默认值。

我在对Caching the Mean of a Vector in R 的makeVector()回答中提供了环境中对象的详细演练。

关于形式在内存中存在多长时间的问题,只要为存储函数的调用实例而创建的环境在内存中,它们就存在。由于垃圾收集器对没有外部引用的对象进行操作,因此如果函数实例未保存到对象中,则只要函数调用将结果返回给父环境,它就有资格进行垃圾收集。

于 2018-04-29T14:29:40.030 回答