【问题标题】:What/Where are the attributes of a function object?函数对象的属性是什么/在哪里?
【发布时间】:2013-04-09 18:48:02
【问题描述】:

通过在 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 的字符串。

所以问题是:

  1. 是否有任何其他对象链接到f?如果有,如何联系他们?

  2. 如果我们去掉f 的属性,使用attributes(f) &lt;- NULL,它似乎不会影响功能。这样做有什么缺点吗?

【问题讨论】:

  • 我对您的#2 声明高度怀疑。除非你已经解决了剥离函数的填充问题,包括间接环境调用、修改其 body 元素,以及很多我不知道的东西,否则你可能想要缓和该声明。
  • @CarlWitthoft,我尝试将attributes(f) &lt;- NULL 与具有不同于R_GlobalEnv 的环境的函数一起使用(实际上在其外壳中查找符号),它仍然有效。此外,使用body&lt;- 会自动将函数从其属性中剥离。考虑到 Josh 在下面的回答,甚至可以选择从一开始就将这些属性保持为空。你能提出另一个需要属性的测试吗?

标签: r function


【解决方案1】:

据我所知,srcref 是唯一通常附加到 S3 函数的属性。 (S4 函数是另一回事,我不建议弄乱它们有时众多的属性)。

srcref 属性用于启用打印函数源代码中包含的 cmets,以及(对于从文件中获取的函数)通过​​行号设置断点,使用 utils::findLineNum() 和 @ 987654324@.

如果你不希望你的函数携带这些额外的行李,你可以通过options(keep.source=FALSE)关闭srcref的录制。来自?options(其中还记录了相关的keep.source.pkgs 选项):

‘keep.source’:当‘TRUE’时,函数的源代码(新 定义或加载)存储在内部,允许 cmets 被保存在正确的地方。通过打印检索源 或使用'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
# }

【讨论】:

  • 非常有趣。似乎print 在没有srcref 属性的情况下使用了函数的body。
  • @Ferdinand.kraft -- 好点子。查看print.function(f1) 与print.function(f1, useSource=FALSE)。
【解决方案2】:

我发现编译函数(包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>

【讨论】:

    猜你喜欢
    • 2014-10-31
    • 2012-12-04
    • 1970-01-01
    • 2015-02-11
    • 2015-07-14
    • 2019-12-31
    • 1970-01-01
    • 2016-02-26
    • 2012-02-06
    相关资源
    最近更新 更多