2013-04-09 2 views
16

Играя с функцией в R, я обнаружил, что в ней есть больше аспектов, чем кажется на первый взгляд.Что/Где атрибуты функционального объекта?

Рассмотрим THS простое задание функции, набранный непосредственно в консоли:

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) <- NULL, это, похоже, не влияет на функцию. Есть ли недостатки в этом?

+0

Я очень скептически отношусь к вашей претензии №2. Если вы не избили начинку из урезанной функции, включая косвенные вызовы окружения, изменяя ее элементы тела, и, скорее, много вещей, о которых я не знаю, вы можете захотеть смягчить эту инструкцию. –

+0

@CarlWitthoft, я попытался использовать атрибуты (f) <- NULL' с функцией, отличной от «R_GlobalEnv» (и фактически ищет символ в своем приложении), и она по-прежнему работает. Кроме того, использование 'body <-' автоматически блокирует функцию из ее атрибутов. Учитывая ответ Джоша ниже, существует даже возможность сохранить эти атрибуты пустым с самого начала. Можете ли вы предложить еще один тест, в котором нужны атрибуты? –

ответ

13

Насколько я знаю, srcref является единственным атрибутом, обычно связанным с функциями S3. (Функции S4 - это другое дело, и я бы не рекомендовал возиться с их иногда многочисленными атрибутами).

Атрибут srcref используется для таких вещей, как позволяет печатать комментарии, включенных в исходном коде функции, и (для функций, которые были источником которых из файла) для установки точек останова по номеру строки, используя utils::findLineNum() и utils::setBreakpoint().

Если вы не хотите, чтобы ваши функции несли такой дополнительный багаж, вы можете отключить запись srcref, выполнив options(keep.source=FALSE). Из ?options (который также документирует, связанные keep.source.pkgs вариант):

«keep.source»: Когда «TRUE», исходный код для функций (недавно определенных или нагруженных) хранится внутри позволяя комментарии к быть в правильных местах.Извлеките источник, напечатав или используя '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 
# } 
+0

Очень интересно. Кажется, что 'print' использует' body' функции, если у нее нет атрибута 'srcref'. –

+0

@ Ferdinand.kraft - Хорошая точка. Проверьте 'print.function (f1)' vs. 'print.function (f1, useSource = FALSE)'. –

3

Я JST понял, атрибут, скомпилированные функции (пакет 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> 
Смежные вопросы