2014-08-28 66 views
1

假設我在R工作區中創建了一個函數列表,同一組函數也在R文件中,並且在source()之後,源函數對象應該與列表中相應的函數相同我創建了,但事實並非如此。函數對象之間的區別R

實施例:

的f.R文件包含f <- function(x) x^2

在該R控制檯:

lst <- list(f=function(x) x^2) 
source("f.R") 
> ls() 
[1] "f" "lst" 
> identical(f,lst$f) 
[1] FALSE 
> str(f) 
function (x) 
- attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 6 1 20 6 20 1 1 
.. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x1b2fd60> 
> str(lst$f) 
function (x) 
- attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 16 1 30 16 30 1 1 
.. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x1bb4b50> 

我也試過:

> identical(f,lst$f, ignore.environment=TRUE) 
[1] FALSE 
> all.equal(f,lst$f) 
[1] TRUE 

這是爲什麼?

編輯:

一般:

f <- function(x) x^2 
g <- function(x) x^2 
identical(f,g) 
[1] FALSE 

爲什麼會的f和g的屬性是不同的?這是否表明不應該使用identical來測試函數對象之間的相等性?

+0

請注意,這不取決於從文件採購;如果你在終端中定義了'f',你將得到相同的結果。有趣的是,如果'f'是一個簡單的'numeric',則不會發生這種情況:'f <-3; lst < - list(f = 3);相同(f,lst $ f)'返回'TRUE'。 – 2014-08-28 09:09:49

+0

否。如果我在終端中定義它,same()將返回TRUE。嘗試'g < - function(x)x + 1''lst < - list(g = g)''same(g,lst $ g)' – ywx 2014-08-28 09:17:49

+1

對不起, X^2;相同(F,列表中(f =函數(X)的x^2)$ F)'。我們深入瞭解R的深奧細節;-) – 2014-08-28 09:22:18

回答

6

你這個證明自己:

> str(f) 
function (x) 
- attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 6 1 20 6 20 1 1 
.. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x1b2fd60> 
> str(lst$f) 
function (x) 
- attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 16 1 30 16 30 1 1 
.. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x1bb4b50> 

這些屬性是不相同的,因此對象是不相同的。

有關這些屬性的更多信息是在這裏:

What/Where are the attributes of a function object?

這些屬性允許R指的是功能的源代碼。你的兩個函數已經在不同的地方定義了,所以它們的源代碼引用(比如它們被定義在哪個文件中)是不同的。

最簡單的區別看到的是srcrefsrcfile屬性:

> attr(attr(f,"srcref"),"srcfile") 
f.R 
> attr(attr(lst$f,"srcref"),"srcfile") 

> 

f功能在f.R定義,所以者繼續在該屬性。您的lst$f在命令行中定義,因此具有空白srcfile屬性。

由於代碼的解析方式,屬性的其他部分也不同。

具體來說,srcfile環境屬性是不同的:

> f <- function(x) x^2 
> g <- function(x) x^2 
> identical(f,g) 
[1] FALSE 
> print.default(attr(attr(g,"srcref"),"srcfile")) 
<environment: 0x5b9fe40> 
attr(,"class") 
[1] "srcfilecopy" "srcfile"  
> print.default(attr(attr(f,"srcref"),"srcfile")) 
<environment: 0x5ba1028> 
attr(,"class") 
[1] "srcfilecopy" "srcfile"  

我想說的函數對象之間的同一性測試可能不是一個很好的事情。唯一可以確信兩種功能是相同的是,如果它是由另一種功能創建的,例如:f2 = f1意味着identical(f1,f2)

任何其他創建函數的方式都會在srcref中產生差異,封閉環境,甚至用括號或不帶括號寫東西。

請注意,如果您將keep.source設置爲FALSE,則可以避免這一切。

> options(keep.source=TRUE) 
> f <- function(x) x^2 
> g <- function(x) x^2 
> identical(f,g) 
[1] FALSE 
> options(keep.source=FALSE) 
> f <- function(x) x^2 
> g <- function(x) x^2 
> identical(f,g) 
[1] TRUE 

但我仍然認爲你需要考慮非常仔細有關的目的是什麼構成相同的功能。

至於參數ignore.environment,它忽略了創建函數的環境。我會寫,創建功能來說明這樣的功能:

foo創建一個「加法器」的功能,增加了x到它的參數:

> foo=function(x){print(x);function(z){z*x}} 

所以我可以使一個附加功能1和一個附加-2功能:

> f1 = foo(1) 
[1] 1 
> f2 = foo(2) 
[1] 2 

這些函數在其環境中存儲本地x。他們是不相同的默認:

> identical(f1,f2) 
[1] FALSE 

但是,如果你忽略他們所創建的環境是相同的:

> identical(f1,f2,ignore.environment=TRUE) 
[1] TRUE 

如果你打印出來,他們看起來是相同的(我已經設置options(keep.source=FALSE)已經)除了環境十六進制代碼參考:

> f1 
function (z) 
{ 
    z * x 
} 
<environment: 0x8e4ea54> 
> f2 
function (z) 
{ 
    z * x 
} 
<environment: 0x8e4fb5c> 

這是ignore.environment忽略的環境。

+0

我看了一下這個鏈接,它讓我知道一個函數具有這樣的屬性。但是這並沒有回答我的問題,就我而言,這些屬性是不同的。 – ywx 2014-08-28 09:30:09

+0

已經添加了一些可以從鏈接中獲得的解釋。 – Spacedman 2014-08-28 10:05:51

+0

感謝您的回覆,但很難理解爲什麼即使兩個函數都是在命令行中定義的,環境屬性也會有所不同。和'相同(f,g,ignore.environment = TRUE)'也會返回FALSE。 – ywx 2014-08-28 11:00:59