2013-04-09 51 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> 
相關問題