2013-04-09 59 views
16

通过玩弄R中的一个函数,我发现它有更多的方面,而不是满足眼睛。什么/哪里是一个函数对象的属性?

考虑的部份简单的功能分配,直接在控制台输入:

f <- function(x)x^2 

通常的“属性”的f,在广义上,是(i)的正式参数列表,(二)身体表达和(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,它似乎不会影响功能。这样做有什么缺点吗?

+0

我非常怀疑你的#2索赔。除非你击败了一个剥离函数,包括间接环境调用,修改它的'body'元素,而不是很多我不知道的东西,你可能想要锻炼那个语句。 – 2013-04-09 19:54:11

+0

@CarlWitthoft,我尝试使用具有不同于'R_GlobalEnv'环境的函数的'attributes(f)< - NULL'(并且实际上在其外壳中查找符号),它仍然有效。另外,使用'body <-'会自动从其属性中剥离函数。考虑到下面的Josh的回答,甚至有一个选项可以从头开始保留这些属性。你能提出另一个需要属性的测试吗? – 2013-04-10 03:09:15

回答

13

据我所知,srcref是通常附加到S3函数的唯一属性。 (S4功能是另一回事,我不会推荐搞乱他们有时候很多的属性)。

srcref的属性可用于改变等使包含在一个函数的源代码注释印刷,和(对于已经从一个源文件中的功能),用于通过行号,设置断点使用utils::findLineNum()utils::setBreakpoint()

如果您不希望自己的功能携带额外的行李,可以通过做options(keep.source=FALSE)关闭srcref的记录。从?options(其也记录了相关keep.source.pkgs选项):

“keep.source”:当“TRUE”,对功能(新 定义或加载)的源代码被存储在内部允许注释到 保持在正确的地方。通过打印 或使用'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 
# } 
+0

非常有趣。看起来'print'在没有'srcref'属性时使用函数的'body'。 – 2013-04-10 03:15:01

+0

@ Ferdinand.kraft - 好点。查看'print.function(f1)'与'print.function(f1,useSource = FALSE)'。 – 2013-04-10 06:29:10

3

我JST想出一个属性,该属性编译的函数(包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> 
相关问题