Inline::Lua - Perl extension for embedding Lua scripts into Perl code
use Inline 'Lua'; print "The answer to life, the universe and everything is ", answer(6, 7), "\n"; __END__ __Lua__ function answer (a, b) return a*b end
Inline::Lua allows you to write functions in Lua. Those of you who are not yet familiar with Lua should have a cursory glance at http://www.lua.org/ to get a taste of this language. In short:
Lua was designed to be embedded into other applications and not so much as a language on its own. However, despite its small set of language features, it is an extremely powerful and expressive language. Its strong areas are an elegant and yet concise syntax, good overall performance and a beautiful implementation of some concepts from the world of functional programming.
Lua code can be included in the usual Inline style. Pass it as string at use time:
use
use Inline Lua => 'function pow (a, b) return a^b end'; print pow(2, 8); # prints 256
Heredocs may come in handy for that:
use Inline Lua => <<EOLUA; function pow (a, b) return a^b end EOLUA print pow(2, 8);
Or append it to your script after the __END__ token:
__END__
use Inline 'Lua'; print pow(2, 8) __END__ __Lua__ function pow (a, b) return a^b end
All of those are equivalent.
Lua datatypes map exceptionally well onto Perl types and vice versa. Lua knows about eight distinct types:
nil
This is Perl's undef
undef
number
A Perl scalar with a, guess what, number in it.
string
A Perl scalar with a string in it.
function
Lua functions act as first class data types. The Perl equivalent is a code-reference.
userdata
Lua being an embeddable language uses this one to handle generic C types. As of now, this is not yet supported by Inline::Lua.
thread
Used to implement coroutines. Not yet handled by Inline::Lua
table
Lua tables act as arrays or hashes depending on what you put into them. Inline::Lua can handle that transparently.
Whenever you call a Lua function, Inline::Lua looks at the arguments you passed to the function and converts them accordingly before executing the Lua code.
Scalars either holding a number, a string or undef are converted to the corresponding Lua types. Considering that those are all very basic types, this is not a very deep concept:
use Inline Lua => <<EOLUA; function luaprint (a) io.write(a) end EOLUA lua_print("foobar"); lua_print(42);
Care must be taken with undef. Lua is less forgiving than Perl in this respect. In particular, nil is not silently transformed into a useful value and you'll get a fatal error from Lua when you try
lua_print(undef);
Inline::Lua offers some means to deal with this problem. See "DEALING WITH UNDEF AND NIL" further below.
Those are turned into Lua tables:
use Inline Lua => <<EOLUA; function print_table (t) table.foreach(t, print) end EOLUA print_table( [1, 2, 3] ); print_table( { key1 => 'val1', key2 => 'val2' } );
This should print:
array: 1 1 2 2 3 3 hash: key1 val1 key2 val2
Nested Perl arrays are handled as well:
print_table( [1, 2, 3, { key1 => 'val' } ] );
will result in
1 1 2 2 3 3 4 table: 0x8148128
That's the real interesting stuff. You are allowed to call Lua functions with function references as arguments and the Lua code will do the right thing:
use Inline Lua => EOLUA function map_print (func, tab) table.foreach(tab, func) end EOLUA sub dump { my ($key, $val) = @_; print "$key => $val\n"; # table.foreach() breaks out when the return value # is non-nill. Hence undef must be returned. return undef; } map_print( \&dump, { key1 => 1, key2 => 2 } );
Here's a bit of currying. The Lua code calls the code-reference passed to it. This code-reference itself returns a reference to a Perl functions which eventually is triggered by Lua and its result is printed:
use Inline Lua => <<EOLUA; function lua_curry (f, a, b) local g = f(a) io.write( g(b) ) -- or simply: io.write( f(a)(b) ) end EOLUA sub curry { my $arg = shift; return sub { return $arg * shift }; } lua_curry( \&curry, 6, 7); # prints 42
It should be obvious that you are also allowed to pass references to anonymous functions, so
lua_curry( sub { my $arg = shift; ... }, 6, 7);
will work just as well.
From a technical point of view, Lua doesn't have a distinct type for that. It uses the userdata type for it. If you pass a reference to a filehandle to your Lua function, Inline::Lua will turn it into the thingy that Lua can deal with:
use Inline Lua => <<EOLUA; function dump_fh (fh) for line in fh:lines() do io.write(line, "\n") end end EOLUA open F, "file" or die $!; dump_fh(\*F);
You must not pass a reference to a scalar to any Lua function. Lua doesn't know about call-by-reference, hence trying it doesn't make much sense. You get a fatal runtime-error when you try for instance this:
function_defined_in_lua (\$var);
Returning stuff from your inlined functions is as trivial as passing them into them.
Those can be translated 1:1 into Perl:
use Inline Lua => <<EOLUA; function return_basic () local num = 42 local str = "twenty-four" local boo = true return num, str, boo, nil end EOLUA my ($num, $str, $boo, $undef) = return_basic();
Whenever you return a Lua table, it gets returned as either a reference to a hash or a reference to an array. This depends on the values in the table. If all keys are numbers, then an array-ref is returned. Otherwise a hash-ref:
use Data::Dumper; use Inline Lua => <<EOLUA; function return_tab () local ary = { 1, 2, 3, [5] = 5 } local hash = { 1, 2, 3, key = 5 } return ary, hash end EOLUA my ($ary, $hash) = return_tab(); print Dumper $ary; print Dumper $hash; __END__ $VAR1 = [ '1', '2', '3', undef, '5' ]; $VAR1 = { '1' => '1', '3' => '3', '2' => '2', 'key' => 'val' };
A couple of things worthy mention: Lua table indexes start at 1 as opposed to 0 in Perl. Inline::Lua will substract 1 from the index if the table is returned as an array so your Perl array will be 0-based. This does not happen for tables that get returned as a hash-reference as you can see in the above example.
Another thing you have to be aware of is potential holes in the array. You can create a Lua table where only the, say, 10000th element is set. Since 10000 is a number, it gets returned as an array. This array naturally will have 9999 undefined elements. In this case it might be better to forcefully turn this key into a string:
local ary = { [ tostring(10000) ] = 1 }
The tables you return can be arbitrarily deeply nested. The returned Perl structure will then also be nested.
What you cannot do is return a Lua table which uses values other than strings or numbers as keys. In Lua, a key can be any object, including a table, a function or whatever. There is no sensible way to mimick this behaviour in Perl so you will get a runtime error if you try something like this:
return { [{1, 2, 3}] = 1 }
There is no limitation on the values you put into a Lua table, though.
If your Lua function returns a function, the function is turned into a Perl function reference. If you are tired of having Perl calulcate the n-th Fibonacci number, let Lua do the hard work. This snippet below shows how a Lua function can return a Fibonacci number generator to Perl:
use Inline Lua => <<EOLUA; function fib () local f f = function (n) if n < 2 then return 1 end return f(n-1) + f(n-2) end return f end EOLUA my $fib = fib(); print $fib->(11); __END__ 144
You can get as fancy as you want. Return a Lua function that itself returns a Lua function that returns another Lua function and so on. There should be no limitations at all.
Just as you can pass filehandles to Lua functions, you may also return them:
use Inline Lua => <<EOLUA; function open_file (filename) return io.open(filename, "r") end EOLUA my $fh = open_file(".bashrc"); while (<$fh>) { ... }
It's a fatal error if your Lua code tries to return a closed filehandle.
You can change undef's default conversion so that Inline::Lua wont transform it to nil when passing the value to Lua:
use Inline Lua => 'DATA', # source code after the __END__ token Undef => 0;
With the above, every undef value is turned into a Lua number with the value 0. Likewise
use Inline Lua => 'DATA', Undef => '';
This will turn undef into the empty string. Any valid Perl scalar can be specified for Undef, this includes references to hashes, arrays, functions etc. A basic example:
use Inline Lua => 'DATA', Undef => 'Undefined value'; print_values(1, 2, 3, undef, 4, 5); __END__ __Lua__ function print_values (...) table.foreachi(arg, print) end
This would come out as
1 1 2 2 3 3 4 Undefined value 5 5 6 6
Sometimes however it is important to return a real nil to Lua. The foreach iterator for example breaks out of the iteration when non-nill has been returned. If you want to use a Perl function as foreach callback, simply having it return undef will therefore not work when Undef was set to some value. Inline::Lua provides a Perl value which is always converted to nil: $Inline::Lua::Nil. Here's an example:
foreach
$Inline::Lua::Nil
use Inline Lua => 'DATA', Undef => 'Undefined value'; map_print( [1, 2, 3], sub { print "@_\n"; return $Inline::Lua::Nil } ); __END__ __Lua__ function map_print (tab, func) table.foreach(tab, func) end
Results in
1 1 2 2 3 3
Lua functions have prototypes. When compiling those functions to bytecode, Inline::Lua looks at their prototype. When calling one of those functions later, it makes sure that the function arguments are padded with undef if you supply less arguments than mentioned in the prototype:
use Inline Lua => <<EOLUA; function foo (a, b, c, ...) print(a, b, c) end EOLUA foo(1); # actually: foo(1, undef, undef)
Those padded undefs are also handled accordingly to the value of Undef. Also note that ... in a prototype is never padded (as you can see in the above).
...
You are allowed to provide whole Lua scripts in your Inline section. Anything outside a function is then run at compile-time:
use Inline 'Lua'; __END__ __Lua__ print(1, 2)
Moreover, Lua scripts may return values to their caller. You can get these values at any point with "Inline::Lua-main_returns">:
"Inline::Lua-
use Inline 'Lua'; my @ret = Inline::Lua->main_returns; __END__ __Lua__ print("I return a list of values") return 1, 2, 3
Note that a Lua script's return value is only retrieved once at compile-time. Hence something like this might not do what you expect:
use Inline 'Lua'; print join "+", Inline::Lua->main_returns; luafunc(); print "\n"; print join "+", Inline::Lua->main_returns; __END__ __Lua__ a = 1 b = 2 function luafunc () a = a + 1 b = b + 1 end return a, b
This will print
1+2 1+2
and not
1+2 2+3
as you might expect.
There must be some. My first suspicion is memory leaks that may hide somewhere in the code. Checking for memory leaks is on my agenda for the next release.
Other than that, you might enjoy an occasional segfault.
If you encounter any of the above, please report it to me.
Check for memory leaks.
Find a smart way to handle objects elegantly.
Look closer at the thread type and figure out whether a sensible conversion exists.
Improve error messages. So far you get messages such as
Attempt to pass unsupported reference type (SCALAR) to Lua at (eval 3) line 6.
In general: Have Inline::Lua croak less often.
Inline
Lua's home can be found at http://www.lua.org/.
Tassilo von Parseval, <tassilo.von.parseval@rwth-aachen.de>
Copyright (C) 2004-2007 by Tassilo von Parseval
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.4 or, at your option, any later version of Perl 5 you may have available.
Lua-5.1.2 Copyright (C) 1994-2007 Lua.org, PUC-Rio.
To install Inline::Lua::Boolean, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Inline::Lua::Boolean
CPAN shell
perl -MCPAN -e shell install Inline::Lua::Boolean
For more information on module installation, please visit the detailed CPAN module installation guide.