Tail recursion
From HaskellWiki
(Difference between revisions)
(Make 'foldl' the object of the link, and move below quote from Brent.) 
(formal definition. vague removed.) 

Line 5:  Line 5:  
not tail recursive. 
not tail recursive. 

−  With that said, tail recursion is not that useful of a concept in a 
+  Here is formal definition of "tail recursive". "<codehaskell>f</codehaskell> occurs in <codehaskell>t</codehaskell>" means <codehaskell>f</codehaskell> is a free variable of <codehaskell>t</codehaskell>. 
−  lazy language like Haskell. The important concept to know in Haskell 

−  is [[guarded recursion]], where any recursive calls occur within a data 

−  constructor (such as <hask>foldr</hask>, where the recursive call to foldr occurs 

−  as an argument to <hask>(:)</hask>). This allows the result of the function to be 

−  consumed lazily, since it can be evaluated up to the data constructor 

−  and the recursive call delayed until needed. 

−  Note that [[Foldfoldl]] is always tail recursive. 
+  When a function is defined (in <codehaskell>let</codehaskell> or at the top level) as: 
+  f = t 

+  where <codehaskell>f</codehaskell> is a name and <codehaskell>t</codehaskell> is a lambdaterm, <codehaskell>f</codehaskell> is ''tail recursive'' iff <codehaskell>f</codehaskell> occurs tail recursively in <codehaskell>t</codehaskell>. <codehaskell>f</codehaskell> ''occurs tail recursively'' in <codehaskell>t</codehaskell> iff <codehaskell>f</codehaskell> occurs in <codehaskell>t</codehaskell> and any of the following holds: 

+  * <codehaskell>t</codehaskell> is variable; 

+  * <codehaskell>t</codehaskell> is "<codehaskell>\var > t0</codehaskell>" and <codehaskell>f</codehaskell> occurs tail recursively in <codehaskell>t0</codehaskell>; 

+  * <codehaskell>t</codehaskell> is "<codehaskell>t0 t1</codehaskell>" and <codehaskell>f</codehaskell> occurs tail recursively in <codehaskell>t0</codehaskell> and does not occur in <codehaskell>t1</codehaskell>; 

+  * <codehaskell>t</codehaskell> is "<codehaskell>let bs in t0</codehaskell>" and <codehaskell>f</codehaskell> occurs tail recursively in <codehaskell>t0</codehaskell> and for each binder "<codehaskell>var = t1</codehaskell>" in <codehaskell>bs</codehaskell>, <codehaskell>f</codehaskell> does not occur in <codehaskell>t1</codehaskell>; 

+  * <codehaskell>t</codehaskell> is "<codehaskell>case t0 of bs</codehaskell>" and <codehaskell>f</codehaskell> does not occur in <codehaskell>t0</codehaskell> and for each branch <codehaskell>b</codehaskell> in <codehaskell>bs</codehaskell>, <codehaskell>f</codehaskell> does not occur or occurs tail recursively in <codehaskell>b</codehaskell>; 

+  ** when we are saying "occur in <codehaskell>b</codehaskell>", <codehaskell>b</codehaskell> has form "<codehaskell>D vars > t</codehaskell>" (where <codehaskell>D</codehaskell> is some data constructor and <codehaskell>vars</codehaskell> is a sequence of names), we are thinking of the lambdaabstraction "<codehaskell>\vars > t</codehaskell>" instead of <codehaskell>b</codehaskell>. 

+  
+  Note that [[Foldfoldl]] is tail recursive. 

+  
+  The important concept to know in Haskell is [[guarded recursion]], where any recursive calls occur within a data constructor (such as <hask>foldr</hask>, where the recursive call to foldr occurs as an argument to <hask>(:)</hask>). This allows the result of the function to be consumed lazily, since it can be evaluated up to the data constructor and the recursive call delayed until needed. 

== Source == 
== Source == 
Revision as of 00:09, 16 June 2010
A recursive function is tail recursive if the final result of the recursive call is the final result of the function itself. If the result of the recursive call must be further processed (say, by adding 1 to it, or consing another element onto the beginning of it), it is not tail recursive.
Here is formal definition of "tail recursive". "f
occurs in t
" means f
is a free variable of t
.
When a function is defined (in let
or at the top level) as:
f = t
where f
is a name and t
is a lambdaterm, f
is tail recursive iff f
occurs tail recursively in t
. f
occurs tail recursively in t
iff f
occurs in t
and any of the following holds:

t
is variable; 
t
is "\var > t0
" andf
occurs tail recursively int0
; 
t
is "t0 t1
" andf
occurs tail recursively int0
and does not occur int1
; 
t
is "let bs in t0
" andf
occurs tail recursively int0
and for each binder "var = t1
" inbs
,f
does not occur int1
; 
t
is "case t0 of bs
" andf
does not occur int0
and for each branchb
inbs
,f
does not occur or occurs tail recursively inb
; when we are saying "occur in
b
",b
has form "D vars > t
" (whereD
is some data constructor andvars
is a sequence of names), we are thinking of the lambdaabstraction "\vars > t
" instead ofb
.
 when we are saying "occur in
Note that foldl is tail recursive.
The important concept to know in Haskell is guarded recursion, where any recursive calls occur within a data constructor (such asfoldr
(:)
Source
 Brent Yorgey in HaskellCafe on Definition of "tail recursive" wrt Folds