Избыточность деревьев синтаксического анализа функций в R

В R я заметил, что дерево синтаксического анализа оператора function кажется избыточным в том смысле, что его четвертый элемент, по-видимому, всегда состоит из первых трех элементов.

Например,

> as.list(substitute(function(x = 1){x^2}))
[[1]]
`function`

[[2]]
[[2]]$x
[1] 1


[[3]]
{
    x^2
}

[[4]]
function(x = 1){x^2}

Одна вещь, которую я заметил, заключалась в том, что четвертый элемент хранит формат, в котором была введена функция.

> as.list(substitute(function(x = 1){
+ x^2})[[4]]
function(x = 1){
x^2}

Какова цель этого четвертого элемента в дереве синтаксического анализа? Единственный раз, когда я вижу, что он используется, - это если вы хотите распечатать функцию дословно, что вы уже можете сделать, напечатав функцию, например.

> f = function(x = 1){
+ x^2}
> f
function(x = 1){
x^2}

person Jon Claus    schedule 11.06.2013    source источник
comment
хороший вопрос; Я ничего не могу найти в определении языка R, но я думаю, что сохранение ссылки на источник — это как раз возможность сохранять (например) комментарии; если я делаю s <- substitute(function(x=1){ ## a comment; x^2}) (разбивая строку точкой с запятой), то str(s[[4]]) показывает, что это объект srcref. Методы для класса srcref выглядят поистине загадочными... (документация: stat.ethz.ch/R-manual/R-patched/library/base/html/srcfile.html )   -  person Ben Bolker    schedule 12.06.2013
comment
Еще одна интересная вещь — выполнение as.list для четвертого элемента, хотя я понятия не имею, что представляет собой результирующий список.   -  person Jon Claus    schedule 12.06.2013
comment
@Бен прав. Чтобы убедиться, что четвертый элемент действительно является просто srcref, посмотрите, что вы получите, когда сделаете это: options(keep.source=FALSE); as.list(substitute(function(x = 1){x^2})). (Или просто проверьте класс четвертого элемента!)   -  person Josh O'Brien    schedule 12.06.2013
comment
@JonClaus: значение результата as.list(s[[4]]) описано в ?srcfile: c(first_line, first_byte, last_line, last_byte, first_column, last_column, first_parsed, last_parsed) в отношении индексов низкоуровневого объекта, представляющего исходный код.   -  person Ben Bolker    schedule 12.06.2013
comment
@BenBolker: Разве вы не должны вставлять свои комментарии в панель ответов?   -  person IRTFM    schedule 12.06.2013
comment
Вот интересная статья Дункана Мердока о ссылках на источники.   -  person Simon O'Hanlon    schedule 12.06.2013


Ответы (2)


Очевидно, этот компонент является ссылкой на источник: его нелегко найти в файле определение языка R, но его назначение как раз и состоит в сохранении структуры исходного кода, особенно комментариев; Например

s <- substitute(function(x=1){ 
      ## a comment
       x^2})
str(s[[4]])
##  Class 'srcref'  atomic [1:8] 1 21 2 15 21 15 1 2
##   ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x8a87634>

показывает, что это объект srcref. Таинственные числа (1, 21, 2, 15, ...) представляют индексы в объект более низкого уровня, представляющий исходный код, как описано в ?srcfile (например, c(first_line, first_byte, last_line, last_byte, first_column, last_column, first_parsed, last_parsed)). Как указывает @SimonO101, есть статья R Journal Дункана Мердока это, вероятно, дает лучшее объяснение.

person Ben Bolker    schedule 12.06.2013

Некоторые дополнительные примечания:

1) Эту функцию можно отключить с помощью options(keep.source=FALSE) (по умолчанию TRUE):

> as.list(substitute(function(x = 1){x^2}))
[[1]]
`function`

[[2]]
[[2]]$x
[1] 1


[[3]]
{
    x^2
}

[[4]]
NULL

В этом list первый элемент является символом, который идентифицирует объект замыкания, второй сохраняет formals, а третий сохраняет body. Обратите внимание, что этот последний печатается «стандартным» способом. Четвертый элемент сохранил бы введенный текст в том виде, в каком он был напечатан.

2) Если вы наберете function(x = 1){x^2} в консоли, R вызовет print.function, который принимает аргумент useSource. По умолчанию это TRUE, и R просто повторяет то, что хранится в четвертом элементе списка разбора. Установка его в FALSE заставляет R напечатать функцию body:

> options(keep.source=TRUE)
> f <- function(x = 1){x^2}
> f
function(x = 1){x^2}
> print.function(f)
function(x = 1){x^2}
> print.function(f, useSource=FALSE)
function (x = 1) 
{
    x^2
}
person Ferdinand.kraft    schedule 12.06.2013