通过在R中使用一个函数,我发现它有更多的方面,而不是眼睛。
考虑简单的函数赋值,直接在控制台中输入:
f <- function(x)x^2
广义上f
的通常“属性”是(i)正式论证清单,(ii)身体表达和(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
的字符串。
所以问题是:
是否有其他对象链接到f
?如果是,如何联系他们?
如果我们使用f
去除attributes(f) <- NULL
的属性,它似乎不会影响该功能。这样做有什么缺点吗?
答案 0 :(得分:13)
据我所知,srcref
是通常附加到S3功能的唯一属性。 (S4功能是另一回事,我不建议弄乱他们有时候很多的属性。)
srcref
属性用于启用函数源代码中包含的注释打印,以及(对于源自文件的函数),用于按行号设置断点,使用utils::findLineNum()
和utils::setBreakpoint()
。
如果您不希望自己的功能携带此类额外行李,则可以通过srcref
关闭options(keep.source=FALSE)
的录制。来自?options
(也记录了相关的keep.source.pkgs
选项):
'keep.source':'TRUE'时,函数的源代码(新的 内部存储,允许注释 保持在正确的地方。通过打印检索源 或者使用'deparse(fn,control =&#34; useSource&#34;)'。
比较
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
# }
答案 1 :(得分:4)
我发现了一个编译函数(包compiler
)具有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>