Recursive functions in Lua 4

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Recursive functions in Lua 4

Ignacio Burgueño
Hi. I have to maintain some Lua 4 code, and I have no idea how to make a
local function call itself.
In the following code, I'd like to make G local to the function F. Is
this possible?

function F()

    G = function(value)
        if value == 10 then
            return "stop"
        end
        return G(value + 1)
    end
   
    print( G(1) )
end

print( F(1) )
assert(not G, "G escaped to the global scope")


Reply | Threaded
Open this post in threaded view
|

Re: Recursive functions in Lua 4

Rob Kendrick
On Thu, 21 May 2009 13:00:56 -0300
Ignacio Burgueño <[hidden email]> wrote:

> Hi. I have to maintain some Lua 4 code, and I have no idea how to
> make a local function call itself.
> In the following code, I'd like to make G local to the function F. Is
> this possible?
>
> function F()
>
>     G = function(value)
>         if value == 10 then
>             return "stop"
>         end
>         return G(value + 1)
>     end
>    
>     print( G(1) )
> end

Yes.  Declare the local variable before assigning to it;

function F()
        local G
        G = function(value)
                if value == 10 then
                        return "stop"
                end
                return G(value + 1)
        end

        print( G(1))
end

B.
Reply | Threaded
Open this post in threaded view
|

Re: Recursive functions in Lua 4

Roberto Ierusalimschy
In reply to this post by Ignacio Burgueño
> Hi. I have to maintain some Lua 4 code, and I have no idea how to make a  
> local function call itself.
> In the following code, I'd like to make G local to the function F. Is  
> this possible?
>
> function F()
>
>    G = function(value)
>        if value == 10 then
>            return "stop"
>        end
>        return G(value + 1)
>    end
>      print( G(1) )
> end
>
> print( F(1) )
> assert(not G, "G escaped to the global scope")

Lua 4 does not have lexical scope, so you should use upvalues. But you
cannot use an upvalue before giving it its final value. One way out
of this is to use a table to create an indirection:

  function F ()
    local t = {}
    t.G = function (value)
            if value == 10 then
              return "stop"
            end
            return %t.G(value + 1)
          end
    print( t.G(1) )
  end

Not pretty, but I cannot think of anything better.

-- Roberto
Reply | Threaded
Open this post in threaded view
|

Re: Recursive functions in Lua 4

Ignacio Burgueño
In reply to this post by Rob Kendrick
Rob Kendrick wrote:

>
> Yes.  Declare the local variable before assigning to it;
>
> function F()
> local G
> G = function(value)
> if value == 10 then
> return "stop"
> end
> return G(value + 1)
> end
>
> print( G(1))
> end


Hi Rob. That works in Lua 5.x, but not in Lua 4.

error: cannot access a variable in outer scope;
   last token read: `G' at line 7 in file `D:\test4.lua'

In order to access G, I have to write %G

function F()
        local G
        G = function(value)
                if value == 10 then
                        return "stop"
                end
                return %G(value + 1)
        end

        print( G(1))
end

print( F(1) )
assert(not G, "G escaped to the global scope")

but then I get
error: attempt to call a nil value
stack traceback:
    1:  function `G' at line 7 [file `D:\test4.lua']
    2:  function `F' at line 10 [file `D:\test4.lua']
    3:  main of file `D:\test4.lua' at line 13

because when the function gets "closed", G is nil.

I found no other way round than calling G and passing itself as an
argument. Is there any other way around this?

Regards,
Ignacio


Reply | Threaded
Open this post in threaded view
|

Re: Recursive functions in Lua 4

Ignacio Burgueño
In reply to this post by Roberto Ierusalimschy
Roberto Ierusalimschy wrote:

> Lua 4 does not have lexical scope, so you should use upvalues. But you
> cannot use an upvalue before giving it its final value. One way out
> of this is to use a table to create an indirection:
>
>   function F ()
>     local t = {}
>     t.G = function (value)
>             if value == 10 then
>               return "stop"
>             end
>             return %t.G(value + 1)
>           end
>     print( t.G(1) )
>   end
>
> Not pretty, but I cannot think of anything better.


Thanks Roberto. I didn't occur to me to use a table. It is prettier than
passing the function around.

Regards,
Ignacio Burgueño