函数对象的属性是什么/在哪里



通过使用R中的函数,我发现它有比表面上更多的方面。

考虑这个简单的函数赋值,直接在控制台中输入:

f <- function(x)x^2

f通常的"属性",在广义上是(i)形式参数列表,(ii)主体表达式和(iii)将作为函数求值框架外壳的环境。可通过以下方式访问:

> formals(f)
$x
> body(f)
x^2
> environment(f)
<environment: R_GlobalEnv>

此外,str返回更多附加到f的信息:

> str(f)
function (x)  
 - attr(*, "srcref")=Class 'srcref'  atomic [1:8] 1 6 1 19 6 19 1 1
  .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x00000000145a3cc8>

让我们试着联系他们:

> attributes(f)
$srcref
function(x)x^2

这是作为文本打印的,但它被存储为数字向量:

> c(attributes(f)$srcref)
[1]  1  6  1 19  6 19  1  1

这个对象也有它自己的属性:

> attributes(attributes(f)$srcref)
$srcfile

$class
[1] "srcref"

第一个是环境,有3个内部对象:

> mode(attributes(attributes(f)$srcref)$srcfile)
[1] "environment"
> ls(attributes(attributes(f)$srcref)$srcfile)
[1] "filename"      "fixedNewlines" "lines" 
> attributes(attributes(f)$srcref)$srcfile$filename
[1] ""
> attributes(attributes(f)$srcref)$srcfile$fixedNewlines
[1] TRUE
> attributes(attributes(f)$srcref)$srcfile$lines
[1] "f <- function(x)x^2" ""

你在这儿!这是R用来打印attributes(f)$srcref的字符串。

问题是:

  1. 是否有任何其他对象链接到f ?如果有,如何联系他们?

  2. 如果我们剥离f的属性,使用attributes(f) <- NULL,它似乎不会影响功能。这样做有什么缺点吗?

据我所知,srcref是通常附加到S3函数的唯一属性。(S4函数是另一回事,我不建议乱改它们有时很多的属性)。

srcref属性用于打印函数源代码中包含的注释,以及(对于从文件中获取的函数)按行号设置断点,使用utils::findLineNum()utils::setBreakpoint()

如果你不想让你的函数携带这些额外的包袱,你可以通过执行options(keep.source=FALSE)来关闭srcref的记录。来自?options(它也记录了相关的keep.source.pkgs选项):

的保持。source ':当' TRUE '时,函数的源代码(new定义或加载)存储在内部,允许注释放在正确的地方。通过打印检索源代码或者使用' deparse(fn, control = "useSource") ' .

比较:

options(keep.source=TRUE)
f1 <- function(x) {
    ## This function is needlessly commented
    x
}
options(keep.source=FALSE)
f2 <- function(x) {
    ## This one is too
    x
}
length(attributes(f1))
# [1] 1
f1
# function(x) {
#     ## This function is needlessly commented
#     x
# }
length(attributes(f2))
# [1] 0
f2
# function (x) 
# {
#     x
# }

我刚刚找出了编译函数(包compiler)具有的attributesstr不可用的属性。这是bytecode .

的例子:

require(compiler)
f <- function(x){ y <- 0; for(i in 1:length(x)) y <- y + x[i]; y }
g <- cmpfun(f)

结果是:

> print(f, useSource=FALSE)
function (x) 
{
    y <- 0
    for (i in 1:length(x)) y <- y + x[i]
    y
}
> print(g, useSource=FALSE)
function (x) 
{
    y <- 0
    for (i in 1:length(x)) y <- y + x[i]
    y
}
<bytecode: 0x0000000010eb29e0>

但是,这在普通命令中不会显示:

> identical(f, g)
[1] TRUE
> identical(f, g, ignore.bytecode=FALSE)
[1] FALSE
> identical(body(f), body(g), ignore.bytecode=FALSE)
[1] TRUE
> identical(attributes(f), attributes(g), ignore.bytecode=FALSE)
[1] TRUE

似乎只能通过.Internal(bodyCode(...)):

访问
> .Internal(bodyCode(f))
{
    y <- 0
    for (i in 1:length(x)) y <- y + x[i]
    y
}
> .Internal(bodyCode(g))
<bytecode: 0x0000000010eb29e0>

最新更新