Here is how I would like to explain recursive functions in R
:
First, I agree with @AEBilgrau that factorial is a good example of recursion. (Better than Fibonacci in my opionion.)
Then I would quickly go through the theoretical basis why a factorial can be defined as a recursive function, something simple, like
4! = 4 * 3 * 2 * 1 = 4 * 3!
Then you can present them with the corresponding recursive function R
fact=function(x) if (x==0) return(1) else return(x*fact(x-1)) fact(3) #6
, but also represent the following conclusion
#|fact(3) called
as obtained from
#helper function for formatting tabs=function(n) paste0("|",rep("\t",n),collapse="") fact=function(x) { #determine length of call stack sfl=length(sys.frames())-1 #we need to define tmp and tmp1 here because they are used in on.exit tmp=NULL tmp1=NULL #on.exit will print the returned function value when we exit the function ... #... ie, when one function call is removed from the stack on.exit({ if (sfl>1) { cat(tabs(sfl),"fact(",x,") returning ", tmp," to waiting fact(",x+1,")\n",sep="") } }) cat(tabs(sfl),"fact(",x,") called\n",sep="") if (x==0) { cat(tabs(sfl),"fact(0)=1 per definition. Nothing to calculate.\n",sep="") #set tmp for printing in on.exit tmp=1 return(1) } else { #print some info for students cat(tabs(sfl),"fact(",x,") is calculated via ",x,"*fact(",x-1,")\n",sep="") cat(tabs(sfl),"fact(",x-1, ") is unknown yet. Therefore calling fact(",x-1,") now\n",sep="") cat(tabs(sfl),"Waiting for result from fact(",x-1,")\n",sep="") #call fact again tmp1=fact(x-1) #more info for students cat(tabs(sfl),"fact(",x,") received ",tmp1," from fact(",x-1,")\n",sep="") tmp=x*tmp1 cat(tabs(sfl),"fact(",x,") can now calculate ", x,"*fact(",x-1,")=",x,"*",tmp1,"=",tmp,"\n",sep="") return(tmp) } } fact(3)