假设我在R工作区中创建了一个函数列表,同一组函数也在一个R文件中,在source()
之后,源函数对象应该与我创建的列表中的相应函数相同,但事实并非如此。
示例:
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 :(得分: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引用函数的源代码。您的两个函数已在不同的位置定义,因此它们的源代码引用(例如它们定义在哪个文件中)是不同的。
最简单的区别是srcfile
的{{1}}属性:
srcref
您的> attr(attr(f,"srcref"),"srcfile")
f.R
> attr(attr(lst$f,"srcref"),"srcfile")
>
函数在f
中定义,因此R会将其保留在属性中。您的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
创建一个&#34;加法器&#34;将foo
添加到其参数的函数:
x
所以我可以创建一个add-1函数和一个add-2函数:
> foo=function(x){print(x);function(z){z*x}}
这些函数将本地> 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>
忽略了环境。