Why does is.recursive return TRUE for a function

Viewed 90

According to the help, is.recursive(x) "returns TRUE if x has a recursive (list-like) structure and FALSE otherwise". I am confused why it returns TRUE when x is a function. For example:

is.recursive(mean)
# [1] TRUE

But it does not seem that functions can be recursive in any meaningful sense, particularly since they are not even sub-settable:

mean[[1]]
# Error in mean[[1]] : object of type 'closure' is not subsettable

Is this an oversight in the R source code, or is there a valid reason that functions should be considered recursive?

2 Answers

A function actually is a recursive structure, I think just for safety reasons they decided not to provide a default method for the [[ function. You can get the more list-like representation with as.list()

str(as.list(mean))
# $ x  : symbol 
# $ ...: symbol 
# $    : language UseMethod("mean")

So what you get is a list for your parameters and then the function body. If you want to get the body directly you can do

body(mean)
body(mean)[[1]]

and that does return the body as an expression that you can subset.

So functions are basically stored as lists of lists, therefore they are recursive.

From the help file ?is.recursive:

Most types of objects are regarded as recursive. Exceptions are the atomic types, NULL, symbols (as given by as.name), S4 objects with slots, external pointers, and—rarely visible from R—weak references and byte code, see typeof.

Since a function isn't one of these types of objects it is not regarded as atomic and is regarded as recursive.

The other way to look at this is that atomic objects can only be a single type of data (an integer, a character, an s4 definition of data, a pointer, etc.). A recursive object is an object that can have multiple types of data in it such as a list. A function can have multiple types of data in it (and philosophically, is a procedure and not a set of atomic data).

Related