Что/Где атрибуты объекта функции?
Играя с функцией в 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"
Первая - это среда с тремя внутренними объектами:
> 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
, это, похоже, не влияет на функцию. Есть ли недостатки в этом?
Ответы
Ответ 1
Насколько я знаю, srcref
- единственный атрибут, обычно привязанный к функциям S3. (Функции S4 - это другое дело, и я бы не рекомендовал возиться с их иногда многочисленными атрибутами).
Атрибут srcref
используется для таких вещей, как включение печати комментариев, включенных в исходный код функции, и (для функций, которые были получены из файла) для установки точек останова по номеру строки, используя utils::findLineNum()
и utils::setBreakpoint()
.
Если вы не хотите, чтобы ваши функции несли такой дополнительный багаж, вы можете отключить запись srcref
, выполнив options(keep.source=FALSE)
. Из ?options
(который также документирует соответствующий параметр keep.source.pkgs
):
'keep.source: Когда "ИСТИНА", исходный код для функций (недавно определенный или загруженный) хранится внутренне, позволяя храниться в нужных местах. Извлечение источника путем печати или используя '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
# }
Ответ 2
I jst вычислил атрибут, который скомпилировал функции (package 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>