Lua and Perl

 | Perl | 2 Comments

Being the hard-core developer type person that I am, every couple of years or so I like to take up a new programming language. This activity provides me with new insights into the wonderful world of programming, seeing how other people tackle interesting problems in different ways.

So last month I picked up a copy of Programming in Lua, and boy has it been a fascinating read. I can definitely recommend purchasing a copy of this book to add to your arsenal of programming literature.

Since my favorite programming language is Perl, each new book I study makes me rethink and compare things about other programming language with Perl (and its potential limitations). This is what I have been doing with Lua.

Two interesting features of Lua which would be great if Perl could do something similar are: "tail-call elimination" and "coroutines".

Tail-call elimination

Basically a tail-call is a goto in disguise. Place as the last statement in a function a return g(x) and you've got a tail-call:

function f(x) return g(x) end

Since the function f(x) has nothing else to do, it doesn't make sense having it wait around until the tail-call returns, using up unused resources like the stack. Might as well avoid using the extra stack space, making it possible to call an unlimited number of nested calls without worrying about the stack overflowing. The following example function can be called forever and the stack will never run out.

function foo(n)
    if n > 0 then return foo(n -1) end
end

A useful example application mentioned in the book, would be traversing a maze with the tail call providing a simple state machine describing going from one cell to the other. Each step goes north, south, east or west into the adjacent room, the exit being the tail-call which transports you from one room to the next.

Coroutines

A coroutine is another wonderful Lua concept. Very similar to threads, it provides a single line of execution within its own context. Several coroutines can work hand in hand, for example in a producer-consumer relationship. You can create, yield and resume coroutines.

Take the example of a producer coroutine reading lines from a file, passing the text to the consumer coroutine. The consumer coroutine receives from the producer.

function consumer (prod)
    while true do
        local x = receive(prod)
        io.write(x, "\n")
    end
end

The send and receive functions provide the gates on each side of the read-write pipe.

function receive (prod)
    local status, value = coroutine.resume(prod)
    return value
end

function send (x)
    coroutine.yield(x)
end

Finally, the producer-coroutine looks like this:

function producer ()
    return coroutine.create(function ()
        while true do
            local x = io.read()
            send(x)
        end
    end)
end

Coroutines can be used for many other things, like iterators or non-preemptive multi-threading applications.

What about Perl?

An interesting challenge could be to see how Perl might be used to implement similar functionalities like those that Lua does natively. As Perl advances and becomes more powerful, it makes sense to see how other programming languages work, and whether or not Perl could be extended to include more advanced concepts.

You'll also want to check out meta-tables and meta-methods, which I believe could be made part of Perl in the not-so distant future.

Official Website

If this all sound confusing, get the book where it's explained clearer and in more detail.

Be sure to check out The Official Lua Website where you will find alot of documentation and tons of examples to whet your curiosity.

2 Comments

Hi there,

for Coroutines, you can use the Coro module. It actually works quite well.

For tail-call elimination, Perl6 has that I believe. There is a goto optimization that could be used to implement tail-call elimination. From the perlfunc manpage:

The "goto−&NAME" form is quite different from the other forms of "goto". In fact, it isn’t a goto in the normal sense at all, and doesn’t have the stigma associated with other gotos. Instead, it exits the current subroutine (losing any changes set by local()) and immediately calls in its place the named subroutine using the current value of @_. This is used by "AUTOLOAD" subroutines that wish to load another subroutine and then pretend that the other subroutine had been called in the first place (except that any modifications to @_ in the current subroutine are propagated to the other subroutine.) After the "goto", not even "caller" will be able to tell that this routine was called first.

NAME needn’t be the name of a subroutine; it can be a scalar variable containing a code reference, or a block that evaluates to a code reference.

Best regards,

hi, your article is fantastic, thanks for sharing that.A++

Leave a comment

Recent Entries

A walk along the Keizersgracht
Too often one is so consumed by a jungle of intertwined thoughts that the beauty of the nearby surroundings ... »
Popularity is fickle
The popularity of a given next generation technology is very fickle, and its success or failure depends on many ... »
Where was Kiffin really buried?
Hi There seems to be some confusion on the current resting place of Kiffin Rockwell, some say that his ... »
Going to Portugal
Normally the week just before I leave for summer vacation, I spend hours on end desperately searching for some ... »
A human language
These days it is not very often that a new and exciting Perl book comes along. That's why I ... »