Recursion in R error

6

I have the following recursive function:

tamanho <- function(v){
  if (is.null(v)){
    return(0)
  }
  i <- tamanho(v[-1])+1
  return(i)
}

I'm using RStudio, and when I call the function with this example:

tamanho(c(1,2,3,5))

gives the following error, and R "resets":

  

R Session Aborted
  R encountered a fatal error.
  The session was terminated.   [Start New Session]

    
asked by anonymous 21.10.2018 / 03:03

1 answer

5

Your role has a logic problem. If v is null, it's all right: it stops. But if v is not null, it will continue doing the recursion indefinitely. Suppose, as in your example, that v <- c(1,2,3,5) :

v <- c(1, 2, 3, 5)
v[-1]
[1] 2 3 5

v[-1] is the v vector without the first element. The second step of your recursive function is to eliminate the second element, which is equivalent to

v[-1][-1]
[1] 3 5

And that works, because R understands that v[-1] is a vector and therefore it is possible to remove its first position, how could it be done with v . But see what happens if we do this a greater number of times:

v
[1] 1 2 3 5
v[-1]
[1] 2 3 5
v[-1][-1]
[1] 3 5
v[-1][-1][-1]
[1] 5
v[-1][-1][-1][-1]
numeric(0)
v[-1][-1][-1][-1][-1]
numeric(0)
v[-1][-1][-1][-1][-1][-1]
numeric(0)

Note that as soon as v is depleted, R continues to try to calculate its size, even if there is no size to calculate, which is what happens from v[-1][-1][-1][-1] . This is because even though it has no element, v[-1][-1][-1][-1] is not null:

is.null(v[-1][-1][-1][-1])
[1] FALSE

Therefore, your program does not have a stop criterion, because is.null does not serve the desired purpose. So much so that when I run your original code on the terminal, instead of crashing like in RStudio, the error response I get is as follows:

tamanho(c(1, 2, 3, 5))
Error: C stack usage  7969280 is too close to the limit

That is, the stack pops (aka stack overflow).

You can solve this with a little change in your code:

tamanho <- function(v){
  i <- 0
  if (!identical(v, numeric(0))){
    i <- tamanho(v[-1]) + 1
  }
  return(i)
}

v <- c(1, 2, 3, 5)
tamanho(v)
[1] 4

identical(v, numeric(0)) will test whether the recursion of v arrives at numeric(0) at some point. ! will deny this. Therefore, recursion will stop only when numeric(0) is true.

Because the test uses numeric(0) as a stop condition, this code is only used to calculate lengths of numeric vectors. It is up to the reader to implement a general version of it, for character, integer, logical vectors, etc.

    
21.10.2018 / 12:39