Pregunta

In R, I noticed that the parse tree of the function operator seems to be redundant in the sense that its fourth element is seemingly always composed of the first three elements.

For example,

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

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


[[3]]
{
    x^2
}

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

One thing I noticed was that the fourth element does store the format in which the function was entered.

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

What is the purpose of this fourth element in the parse tree? The only time I can see it being used is if you wanted to print a function verbatim, which you can already do by printing the function, e.g.

> f = function(x = 1){
+ x^2}
> f
function(x = 1){
x^2}
¿Fue útil?

Solución

Apparently this component is a source reference: it's not easily located in the R language definition, but its purpose is precisely for retaining the structure of the original source, especially comments; for example

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>

shows that it's a srcref object. The mysterious numbers (1, 21, 2, 15, ...) represent indices into a lower-level object representing the source code, as described in the ?srcfile page (i.e. c(first_line, first_byte, last_line, last_byte, first_column, last_column, first_parsed, last_parsed)). As @SimonO101 points out, there's an R Journal article by Duncan Murdoch that probably gives the best explanation.

Otros consejos

Some additional notes:

1) It's possible to disable this feature using the options(keep.source=FALSE) (the default is TRUE):

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

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


[[3]]
{
    x^2
}

[[4]]
NULL

In this list, the first element is a symbol that identifies a closure object, the second saves the formals and the third saves the body. Note that this last one is printed in a "standard" way. The fourth element would have saved the input text, as typed.

2) If you type function(x = 1){x^2} at the console, R calls print.function, which accepts a useSource argument. This is TRUE by default, and causes R to simply repeat what is stored in the fourth element of the parse list. Setting it to FALSE forces R to print the function 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
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top