lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Gabor Grothendieck <ggrothendieck <at> myway.com> writes:

: 
: Rici Lake <lua <at> ricilake.net> writes:
: 
: : 
: : On 22-Jul-04, at 9:31 PM, Gabor Grothendieck wrote:
: : >
: : > For example, we can invoke the anonymous factorial function
: : > evaluating it for the argument 3 like this:
: : >
: : >    Recall = function(...)
: : >      return debug.getinfo(2,"f").func(unpack(arg))
: : >    end
: : 
: : The use of the debug library is not advisable, unless you are actually 
: : debugging. Furthermore, this will not work on the tail-recursive 
: : implementation of factorial:
: : 
: : print ((function(x, acc)
: :            if x <= 1 then return acc
: :                      else return Recall(x - 1, x * acc)
: :            end
: :          end) (3, 1))
: : 
: : stdin:1: attempt to call field `func' (a nil value)
: 
: That's too bad; however, one can still do it in a consistent,
: but uglier, way for both examples by using 
: 
:    debug.getinfo(1,"f").func
: 
: inline like this:
: 
:    print ((function(x)
:            if x == 0 then return 1
:                      else return x * debug.getinfo(1,"f").func(x - 1)
:            end
:          end) (3, 1))
: 
:    print ((function(x, acc)
:            if x <= 1 then return acc
:                      else return debug.getinfo(1,"f").func(x - 1, x * acc)
:            end
:          end) (3, 1))

Here is a slight improvement.  If one defines Recall to return the 
function, itself, rather than the function evaluated, then Recall can
still be used in both the non-tail recursion and tail recursion cases
like this:

   Recall = function() return debug.getinfo(2,"f").func end

   print ((function(x)  -- non-tail recursion example
      if x == 0 then return 1
         else return x * Recall()(x-1)
      end
   end) (3))
  
   print((function(x, acc) -- tail recursion example
           if x <= 1 then return acc
              else 
                 local Recall = Recall()
                 return Recall(x - 1, x * acc)
           end
       end)(3,1))


We could have made this entirely symmetric by writing the
non-tail recursion case using the local redefinition of
Recall, as well, like this:

   print ((function(x)  -- non-tail recursion version 2
      if x == 0 then return 1
         else
            local Recall = Recall() 
            return x * Recall(x-1)
      end
   end) (3))