2013-04-09 14 views
16

は、私が目を満たしているよりも、それへの多くの側面があるがわかりました。関数オブジェクトの属性は何ですか/どこですか? R内の関数で遊んことで

f <- function(x)x^2 

通常fの「属性」、広い意味では、(I)仮引数のリスト、(ⅱ)以下のとおりです。

はTHSシンプルな機能の割り当ては、コンソールで直接入力を検討します(iii)機能評価フレームのエンクロージャとなる環境に依存している。 、これはテキストとして印刷されている

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

:のは、それらに到達してみましょう

> 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> 

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

また、str戻っ詳細はfに添付:彼らは、経由してアクセスできます

> 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. attributes(f) <- NULLを使用して属性のfを削除しても、機能には影響しないようです。これには何らかの欠点がありますか?

+0

あなたの2番の主張は非常に懐疑的です。間接的な環境呼び出しや、 'body'要素の変更を含む、剥奪された関数からの詰め物を叩いた場合を除いて、私はそれについて気づかないかもしれません。 –

+0

@CarlWitthoft、 'R_GlobalEnv'とは異なる環境で(実際にはエンクロージャ内のシンボルを探す)関数で' attributes(f)< - NULL'を使ってみましたが、それでも動作します。また、 'body < - 'を使うと自動的にその属性から関数を取り除きます。以下のジョシュの答えを考えれば、これらの属性を最初から空にすることさえできます。属性が必要な場所で別のテストを提案できますか? –

答えて

13

私が知る限り、srcrefは、S3機能に通常付加される唯一の属性です。 (S4関数は別の問題であり、時には数多くの属性を混乱させることはお勧めしません)。

srcref属性は、とutils::findLineNum()utils::setBreakpoint()を使用して、行番号でブレークポイントを設定する(ファイルから調達されている機能のために)関数のソースコードに含まれるコメントの印刷を可能にするようなもののために使用されています。

このような追加手荷物を携帯したくない場合は、options(keep.source=FALSE)を実行して、srcrefの録音をオフにすることができます。

「keep.source」:?options(また、関連keep.source.pkgsオプションを文書化する)から「TRUE」、関数のソースコードは、(新た 定義またはロード) にコメントを保持することができるように内部に格納されています正しい場所に を出力するか、または 'deparse(fn、control = "useSource")'を使用してソースを取得します。

比較:私はコンパイルされた関数(パッケージcompiler)が持っている属性を考え出しJST

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'を使います。 –

+0

@ Ferdinand.kraft - 良い点。 'print.function(f1)'と 'print.function(f1、useSource = FALSE)'を比較してみてください。 –

3

ことがattributesまたはstrでは使用できません。それは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>