
Why Lua? - tlowrimore
http://blog.datamules.com/blog/2012/01/30/why-lua/
======
alanfalcon
I took some Visual Basic programming courses in high school, some PASCAL
courses in college, and then didn't program anything other than basic HTML/CSS
for the next eight years. Last year I programmed an iPhone game in Lua (using
the Corona SDK) and it was easy as Tau. Sure a better programmer would have
finished the programming aspects in a quarter the time it took me, but I
started by looking at Objective-C and I'm not sure I ever would have picked it
up without some kind of formal training. Contrast with Corona/Lua, where I
watched a few eight minute videos on YouTube and could turn around and make
simple but complete programs, and more importantly completely understand what
was going on within them. Reading the Lua documentation was a revelation,
reading Apple's was a headache.

Why Lua? <http://itunes.apple.com/us/app/beat-boxes/id460798042>

~~~
sixcorners
Doesn't Apple forbid applications built using things like this?

~~~
evgen
As long as you are not running code that is downloaded after app install (e.g.
either embedded in the app itself or entered by the user from the keyboard)
you are good to go. This mod to the previously ominous app store policies is
used by quite a lot of applications.

------
haberman
The more I learn about Lua's design and implementation, the more impressed I
am. It's very rare to see software that does so much with so little code. The
design is extremely clean and the code is extremely fast.

The C API is easy to use and gives good performance, and yet encapsulates
enough of the VM's implementation that C modules are source _and binary_
compatible with both Lua and LuaJIT, two very different implementations of
Lua. Note that the C API was designed before LuaJIT was even written, so this
API was designed without the benefit of seeing how different implementations
of Lua might vary.

The source is very readable for the most part; my only stumbling block is that
their naming of types and variables is extremely terse at the cost of
readability sometimes, and the extensive use of macros can sometimes can
require a lot of jumping around. But Lua is an impressive achievement that I
frequently refer to for design inspiration.

~~~
sshumaker
Lua has great C integration, but LuaJIT's is even better. You can natively
interface with C code without a recompile, just by defining the C function
prototype in Lua, and using it like you would any normal lua function. Better
still, LuaJIT can frequently inline the calls to C code, so there's no cross-
language marshaling penalty.

Check out <http://luajit.org/ext_ffi_tutorial.html>

~~~
haberman
FFI is extremely cool and impressive, no doubt, but a major downside of it is
that you give up memory safety. Once you import it your Lua program can SEGV
the interpreter and read/write arbitrary memory in your process. Freedom from
memory errors is a major motivation for using high-level languages, so this
should not be given up lightly. Also, from a security standpoint it means your
Lua is less sandboxed.

~~~
sshumaker
Yes, but you use it to interface with native code. Normally, you'd write
Lua_Cfunctions to achieve the same behavior - and those can crash your app
just as easily, since they're native code. Perhaps more so, since it's easy to
screw up the stack manipulation.

~~~
haberman
Yes, but the point is that once you've loaded FFI you have to trust 100% of
the Lua. With a Lua C extension you have to trust the extension, but not the
Lua that loads it.

~~~
justincormack
You can still sandbox it and not provide direct access to ffi to user code,
only some tested ffi calls. Just like native in that way.

~~~
haberman
If FFI is loadable, how are you going to prevent your untrusted script from
loading it and going to town? How are you going to avoid providing "direct
access?" My whole point is that I don't think you can. It's all or nothing. If
ffi is available to some Lua code, it is available to all of it.

I even asked Mike Paul (LuaJIT author this question, and he said "That's not a
viable approach for sandboxing.") <http://lua-
users.org/lists/lua-l/2011-02/msg01582.html>

------
chubot
Why isn't Lua more widely used? One reason is a consequence of it being an
embedded language. Lua has had 5 major versions which are _very_ incompatible
with each other. You're just supposed to stick with the previous version until
you upgrade your code.

I read all the Lua papers, and they are quite fond of "getting it right"
(which is refreshing). They will break things to get it right, whereas other
languages stick with all their old design warts in the name of compatibility.
I like this approach, but it comes at the expense of popularity.

Compare Lua with Python, which has had basically 1 major version for 20 years
Python 1.x are all compatible with 2.x -- that was a license change; and
Python 3 is having adoption troubles which proves the same point. Python 3 was
the chance to "get things right", or fix old design warts, but you can see
what a big impact it's having on adoption, fragmentation of libraries, etc.

The other reason is that embedding a language isn't as common a use case as a
scripting language. I've tried to write stuff in Lua rather than Python, but
really Python's "batteries included" philosophy just kills any advantage Lua
has.

The main reason I would like Lua is so you can distribute stable (small)
executables... but when you're starting out Python is a lot easier. You don't
want to download LuaSocket or whatever and mess with the build system.

~~~
moe
_Why isn't Lua more widely used?_

I think the major, overwhelming reason is because it has no standard library,
much less a package-ecosystem such as RubyGems or Python eggs.

~~~
ZitchDog
You do know about LuaRocks, right? It's not as robust or vibrant as the Ruby
or Python equivalent, but it certainly does exist.

<http://luarocks.org/repositories/rocks/>

~~~
moe
Ah, I did in fact not know about it, thanks for the pointer!

Maybe there's still hope! ;-)

------
groovy2shoes
Good article, but one nitpick: not _everything_ in Lua is a table. Tables are
a versatile data structure that can be used as arrays, dictionaries, objects,
etc. However, Lua provides many types besides tables: numbers, booleans,
closures (functions), strings (which are interned), coroutines, and something
called userdata (which are typically pointers to something implemented in C).

Another cool thing about Lua, which was mentioned only briefly in the article,
is proper tail-call optimization (TCO) like you'd find in Scheme. TCO makes
expressing recursive algorithms nicer because you don't have to worry about
blowing your stack.

Lua's design philosophy -- giving the programmer a handful of basic yet
powerful features -- makes it somewhat Schemy. I suspect that Lua is about as
close as you can get to a ball of mud before becoming Lisp.

~~~
jballanc
To nitpick your nitpick: in Lua tables are the only _composite_ data
structure. Everything you listed is either atomic or opaque (you can hide
composite datatypes in userdata, but you can't introspect the values).

If you think about it, this is very similar to C where the only composite
datatype is a struct (arrays are just sugar on pointer arithmetic). In fact, I
think if you wanted to make a scriptable dialect of C, you'd create Lua.

Of course, by being simple, add in dynamic typing and first-class functions,
and Lua does feel a bit like Scheme's kid brother. Or, rather, Lua (in my
mind) reveals how C and Scheme aren't so far apart after all!

~~~
zeen
Well, since we are nitpicking nitpicks, allow me to nitpick your nitpick of a
nitpick: Lua closures are also composite data structures. You can get/set
their upvalues via the debug API. Behold:

    
    
      function create()
        local a,b,c,d,e,f,g,h,i,j;
        return function() print(a,b,c,d,e,f,g,h,i,j); end
      end
      function array_get(f, index)
        local k,v = debug.getupvalue(f, index);
        return v;
      end
      function array_set(f, index, value)
        debug.setupvalue(f, index, value);
      end
      function map_get(f, key)
        for i=1,math.huge do
          local k,v = debug.getupvalue(f, i);
          if k == key then return v; end
          if k == nil then return nil; end
        end
      end
      function map_set(f, key, value)
        for i=1,math.huge do
          local k,v = debug.getupvalue(f, i);
          if k == nil then return; end
          if k == key then
            debug.setupvalue(f, i, value);
            return;
          end
        end
      end
      
      function test()
        local f = create();
        array_set(f, 1, "one")
        assert(array_get(f, 1) == "one");
        map_set(f, "b", "something");
        assert(map_get(f, "b") == "something");
        print("Success!")
      end
      test();
    

If table creation was disallowed, you could use functions in place of tables.
And you could repurpose an existing table as the function type's metatable,
allowing syntax like func.x=func[y]

Oh, and coroutines probably also fall under composite data structures
technically...

~~~
jballanc
Very well played! If I were the nitpick-y type ;) I'd wonder whether use of
the debug library is kosher (esp. in production code), but you are definitely
correct. Though, actually, this again correlates very closely with C/Scheme --
You _can_ use an offset from a stack frame pointer to access stack variables
in a function scope in C; and upvalues are just closed-over variables _a la_
Scheme closures.

Actually, that's another point in Lua's favor. The mechanism Lua uses for
managing closed-over variables is _WAY_ more elegant than, for example, Ruby's
mechanism...

------
gregholmberg
_Speed & Simplicity_

 _LuaJIT speeds can rival code written in C. And if you are still not getting
the speed you want, see my 1st point above (Integration with C and C++ for
that matter)._

The simplicity of Lua is, I think, really underrated.

It is a good learning exercise to write some small benchmark / utility / tool
in Lua so you can get an idea of how quickly you can develop, and how fast the
resulting code will be.

Then read through the Lua source [0] to see just how little code is required
to give you that platform for your ideas.

[0] <http://www.lua.org/source/5.1/lua.c.html>

~~~
loup-vaillant
The simplicity of _any code_ is really underrated. Like 4 orders of magnitude
underrated: <http://www.vpri.org/html/work/ifnct.htm> (Long story short: a
typical mainstream desktop weights more than 200 millions lines of code. The
guys at the Viewpoint Research Institute can simplify it down to 20.000
lines.)

~~~
groby_b
"We have a technique to reduce the complexity by four orders of magnitude, but
unfortunately can't even give a summary of that technique here".

I reserve judgment till I see an actual proof of that.

~~~
loup-vaillant
The proof is not far. See their last report here:
<http://www.vpri.org/pdf/tr2011004_steps11.pdf> Also, a good deal of their
code is accessible here:
<http://vpri.org/fonc_wiki/index.php/Installation_Guide>

As far as I can tell, several things can explain how they fit a whole library
in a single book (assuming 50 lines per page, 400 page books, 10.000 books in
a library). First, the use of dedicated languages instead of C and C++ seems
to explain 2 orders of magnitude. The 2 remaining ones are explained by
feature creep and plain lack of reuse (in the Franck system for instance, they
use a single library to draw everything, from characters in a word processor
to the frames of the windows.)

They also claim specific achievements: a full self-implementing compilation
stack in less than 2Kloc, on top of which implementing something like
Javascript or Prolog takes less than 200 lines (see
<http://piumarta.com/software/maru> for actual code). A Lex/Yacc equivalent in
400 lines or so (see <http://www.tinlizzie.org/ometa/> for actual code). A
Cairo equivalent that run with acceptable performance in about 500 lines. A
TCP-IP stack in 160 lines, stable enough to run a web site.

If half of that is true, we can effectively talk about a silver bullet. That
bullet won't kill the complexity werewolf of course, but it will seriously
cripple it.

~~~
groby_b
Looking at OMeta, it seems to use libcairo and X11. It's hardly fair to _not_
count those lines. Same goes for dedicated languages. If I don't have to count
my toolchain, and I'm allowed specialized languages, I can do everything in
one line...

    
    
       DoAwesomeStuffJustLikeILikeIt();
    

Don't get me wrong, there's some cool stuff there - but the claims of 4 orders
of magnitude seem exaggerated to me.

~~~
loup-vaillant
Wait, what? OMeta uses _libcairo_ and _X11_?! Where did you see that? The only
thing I saw it use is a host programming language (Javascript or Python or
Ruby…). You may want to count those lines instead. Anyway, remember that they
also claim a full language stack in less than 2000 lines. Including a variant
of OMeta. Even Lua is 5 times as big. Not counting GCC.

I know it's unbelievable. But other personal experiences make me think they're
probably right. I have written equivalent OCaml and C++ code where the C++
version were 5 times larger (both where optimized for clarity). In my day job,
I routinely divide substantial portions of C++ code by 2 through light
refactoring.

VPRI's miracle doesn't only come from the awesomeness of their ideas. It also
comes from the awfulness of current systems. A full desktop in 20.000 lines
may not be so small, if you consider that current ones are way too big.

Addendum: I omitted a rather important detail: while the STEPS project aims to
build a full desktop system, along with networking, publishing, messaging, and
programming capabilities, it makes no attempt be compatible with anything
(except the hardware on which it has to run). It doesn't do HTTP nor HTML, for
instance.

~~~
groby_b
Based on a cursory glance at the sources. Maybe I'm misreading things, or
maybe it's an intermediate version - certainly possible.

And, to be clear, I _do_ believe there are substantial savings in program size
to be had. ( _Especially_ over C++. Chatty little monster ;)

It's the 4 orders of magnitude that make me doubtful. The good thing, AFAIK
VPRI is a year or so from completion, so we'll see soon. And even if it's not
4 orders of magnitude, I'm sure there's a lot to learn from it.

------
whatajoke
Not criicizing lua, but worth comparing to guile.

> Integration with C (and C++ for that matter)

Guile does it better. You can use shared memory threads in guile without any
penalty. Atmost you have to allow for the garbage collector to run when inside
FFI functions. But that is a small price to pay in case you need to use
multiple parallel-concurrent threads with a single heap.

Guile was built with FFI in mind and has an impressive history. Just take a
look at guile gnome bindings.

> Speed and Simplicity

Guile 2 is extremely fast. Not as fast as LuaJIT, but it no reason it won't
get there. As for simplicity, take a look at the partial evaluator in trunk of
guile 2.

> Education

Guile is good old scheme.

> Functional

Can't get more functional than scheme :)

> Everything is a Table

Well, almost everything is a pair in guile. Vectors and hash-tables are
trivially available. Though I recommend to sticking to functional programming
in scheme style.

> Consistent

As before, can't get more consistent than scheme.

> Portable

Guile is available on n900. So there.

To continue, guile has continuations (delimited or otherwise), and macros
(hygienic or otherwise), both of which are effectively missing in lua.

And guile offers all of this while supporting native threading with a single
heap. Sweeet.

~~~
sshumaker
Not sure if I'd agree that Guile's FFI bindings are better than LuaJIT's FFI.
It's certainly easier to declare a function in LuaJIT - you can take the
definition directly from the header file, rather than transcoding it into
s-exps.

Compare:

    
    
      (define memcpy
    	       (let ((this (dynamic-link)))
    	         (pointer->procedure '*
    	                             (dynamic-func "memcpy" this)
    	                             (list '* '* size_t))))
    

vs.

    
    
      ffi.cdef [[
    	void * memcpy ( void * destination, const void * source, size_t num );
      ]]
    

You also get the ability to add metamethods and finalizers to returned C
objects (so you can use Lua's built-in GC to clean up after, for example, your
FILE*).

As for the speed, there's no reason that a lot of dynamic languages couldn't
be as fast as LuaJIT. But none of them are even close. I wish LuaJIT was still
up in the computer language shootout. The LuaJIT interpreter (with JIT turned
off) is 3x faster than V8 on the PC, and faster than Java on Android. And
that's the interpreter - the JITed code is way faster.

Of course, macros are awesome, and a huge point in Guile's favor. On the plus
side, Lua is very easy to understand, especially if you're coming from
Javascript.

~~~
cmf028
"As for the speed, there's no reason that a lot of dynamic languages couldn't
be as fast as LuaJIT. But none of them are even close. I wish LuaJIT was still
up in the computer language shootout. The LuaJIT interpreter (with JIT turned
off) is 3x faster than V8 on the PC, and faster than Java on Android. And
that's the interpreter - the JITed code is way faster."

[Citation Needed]

I know of old benchmarks (pre Crankshaft) that showed the interpreter being
faster than V8, but my own tests using the same benchmarks from the computer
language shootout show V8 to be about 1.5x faster than luaJIT now.

I did some searching, and the most recent (though still way out of date)
comparison I could find was this: <http://attractivechaos.github.com/plb/>

~~~
sshumaker
You can compare v8 to vanilla lua on the computer language shootout benchmarks
page, and then compare luajit to lua on the luajit page. V8 has definitely
made up some ground, and the luajit interpreter isn't generally faster than
v8, but the jit is still way faster on almost all tests. The one area where
luajit isn't great is on tests that stress garbage collection, since luajit
still uses vanilla lua's GC. I think that's luajit's next area of focus.

------
marshray
To echo chubot: Why isn't Lua more widely used?

* It lacks an easy-to-use symbolic debugger.

* It lacks a first-rate IDE.

* It lacks a standard way for people coming from OO/Java to define objects and interfaces.

* It lacks a GUI toolkit.

* It has a great set of manuals. It lacks an O'Reilly book with a woodcut animal on the cover.

* Arrays indexes start at 1.

Except for the last item, these are all relatively small things that are
simply waiting for someone to come along and do them. This is a testament to
the great design of the language.

And many of these things do exist, it's just the Lua style seems to be to
understate the achievements to the point that folks can't tell the big new
stuff from the abandoned projects.

~~~
fab13n
> * It lacks an easy-to-use symbolic debugger.

> * It lacks a first-rate IDE.

<plug>This is changing
[http://eclipse.org/koneki/ldt/</plug>](http://eclipse.org/koneki/ldt/</plug>);

> * Array indexes start at 1.

This sounds dangerously similar to "I can't use Python because it has
significant whitespaces". Developers might like or dislike it, but if you
can't get over _that_, you either lack important cognitive abilities, or
you're suffering from a very serious case of Asperger's/OCD. I can't imagine
that someone seriously hampered by _that_ could ever digest any large API.

However, I'll admit it's a bit irritating when you're frantically switching
between C and Lua.

> the Lua style seems to be to understate the achievements to the point that
> folks can't tell the big new stuff from the abandoned projects.

You're right, organizing the efforts of the Lua "community" would probably be
trickier than herding cats, and the Lua core team doesn't seem very interested
in helping that happen. I sometimes suspect that even Lispers form a tighter
community than Lua hackers...

~~~
eridius
> > * Array indexes start at 1.

> [...]

> However, I'll admit it's a bit irritating when you're frantically switching
> between C and Lua.

I would imagine it can be confusing when swapping between C and Lua, but when
working in a Lua-only environment (e.g. writing addons for World of Warcraft)
it very quickly becomes a non-issue.

------
ammmir
lua (the language and core libraries) is stable and small. many developers are
attracted to node.js or rails due to the community ("look, everyone else is
doing it!"), ecosystem (abundance of modules/gems to choose from), and rapid
release cycles.

lua seems to have more of a relaxed, niche community among game developers and
scripting language embedders.

i've been using lua for about a week so far, for a music player i'm building
(<http://cloudplay.fm/>) and i'm writing the song search/ranking system in
lua. it's wonderful to be able to prototype it outside the application and not
have to deal with the integration until you need to.

i would consider using lua on the server-side (see <http://luvit.io/> for a
node.js-style interpretation, although i'd prefer coroutines instead of
callbacks) but there needs to be more work on the library front.

to help lua grow, i'd fix these things:

\- add unicode support

\- bring the CLI up to par with node.js (i use node as a calculator, too)

\- build a modern distribution that includes frequently used luarocks

~~~
jacques_chester
> add unicode support

This won't happen soon. Lua targets ANSI C and only ANSI C.

C11 includes new character types to support unicode, but I imagine that the
Lua implementers will take their time.

Plus there's implications for embedded situations.

If you need unicode (and most do), there are libraries and patches that do a
reasonable job.

~~~
marshray
I'm fine with C-style strings, but once in a while there are things for which
a bit of UTF-8 tagging would be good enough.

~~~
groovy2shoes
Lua strings aren't C-style: they're prefixed with the string length. Lua's
strings are suitable enough to store UTF-8 encoded data, but none of Lua's
built-in functions are equipped to process it. Unicode libraries don't need to
provide a special Unicode string type, they simply need to provide Unicode-
aware string processing functions.

~~~
marshray
Right. I meant "C-style" in the sense of Lua being oriented around the kind of
single/multibyte encodings used with ANSI C (as contrasted with kind of the
UCS-2 and UTF-16 stuff you get with Win32 and Java).

------
leafo
Lua is a great platform, but I think there are a lot of areas where it can be
made more programmer friendly. That's why I wrote <http://moonscript.org/>

~~~
rlander
I was about to mention how cool Moonscript is, but you beat me to it. =)
Thanks for the awesome project!

------
hythloday
I love Lua, but when I read statements like this:

>>> In Python, you might __import__('...')' some module and then the variables
of the return value would be accessed like vars(module)

it makes me wonder if the author is just unfamiliar with Python (and by
extension, any language other than Lua) or if they're deliberately
misrepresenting other languages to make Lua look good (which it definitely
doesn't need).

~~~
ktr
Sorry, I would actually consider myself quite proficient in Python. What I was
trying to [unsuccessfully] show was that the underlying mechanics of Python's
import mechanism are different then, say, Python's dict or list
implementations. Whereas in Lua everything really is just a table. I ran into
this (in Python) when I was trying to dynamically import code based on command
line arguments and access the functions in said script as strings. So in Lua,
you just `x = require"script" ; x["fn"]` whereas in Python you sort of need to
know this information up front unless you go through the machinations I
outlined in the article.

But this was obviously a poorly written part of the article that could use
improvement.

[EDIT] typos [EDIT2] less arrogance :)

~~~
hythloday
Hey, thanks for the reply, I do see your point now--I thought you were
referring to the usual case of importing modules. It's true that Python
modules aren't implemented in terms of dicts or lists and that Python is a
larger language than Lua, so I think I completely agree with the point you
were making. :)

For future reference, I'd implement your dynamic module importer like this:

    
    
      def dynamic_import(name):
           import imp
           return imp.load_module(name, *import.find_module(name))
    
      os = dynamic_import("os")

~~~
ktr
Thanks for the pointer! I'll have to keep that in mind.

------
timmaxw
I've used Lua for a couple of personal projects. My main objection to it is
that accessing an undefined variable or member returns nil rather than
throwing an exception. If you make a typo, you don't find out until you try to
call or perform arithmetic on your nil value. Since inserting nil into a table
just deletes that key of the table, the use site might be several steps away
from the typo.

Other than that, I agree with the other posters here. It's an impressively
lightweight and elegant language. It's especially good for embedding: its C
integration is next to none, it's easy to sandbox if you want to run untrusted
code, and the interpreter doesn't use any global variables.

~~~
sshumaker
You can fix that easily with a metatable.

    
    
      function nilguard(tbl)
        tbl = tbl or {}
        local mt = {
          __index = function(t,k)
            error("Invalid key: " .. tostring(tbl) .. "[" .. k .. "]")
          end
        }
        setmetatable(tbl, mt)
        return tbl
      end
    
      local myObj = nilguard({foo=10})
      myObj.crap -- should raise
    

For undefined global variables, just require("strict")

------
JoshTriplett
For a different perspective, take a look at
<http://julien.danjou.info/blog/2011/why-not-lua> (submitted to HN as
<http://news.ycombinator.com/item?id=3536131> ).

------
ww520
Does anyone know how good is Lua's support for async IO? Especially the
handling of large amount of connections and the memory footprint for each
connection?

~~~
silentbicycle
Luasocket does async IO. It uses poll or select on Unix (calling it 'select');
I'm not familiar with what it uses on Windows. It's not "web scale", but is
very easy to use, and works well enough for a couple hundred simultaneous
connections.

Lua's convenient C API means that wrapping libev, libuv, or libevent is really
not hard, if you want to go that route. (I have a libev wrapper on github,
FWIW.)

The thing to keep in mind is that if you're writing high-throughput servers,
you probably want to avoid parsing the network IO via Lua. While Lua strings
are fine with arbitrary binary data (i.e., \0s are fine), it interns all
strings; you'll have the overhead of converting every read into an
atom/symbol, and it will spend a lot of time garbage collecting. (Lua makes
this daring trade-off because it's _usually_ a net win, and when it isn't, you
still have the option of doing things in C instead.) Lua's great for handling
all the control logic, though. Coroutines are particularly applicable there.

In a nutshell: If you're good with C, and understand the issues involved with
performant async IO, Lua can work _very_ well.

~~~
ww520
Thanks for the info. Very informative reply. Sounds like the network handling
stuff should be in the C layer. And pass the parsed message/objects back to
Lua is the way to go.

~~~
justincormack
Or use the LuaJIT ffi which fives you access to native C arrays at native
speed.

------
gregholmberg
Why Lua?

Because the Wikimedia Foundation has decided to use it?

"Wikipedia chooses Lua as its new template/macro language"
<http://news.ycombinator.com/item?id=3534649>

"Lua chosen as new template scripting language"
[http://en.wikipedia.org/wiki/Wikipedia:Wikipedia_Signpost/20...](http://en.wikipedia.org/wiki/Wikipedia:Wikipedia_Signpost/2012-01-30/Technology_report)

------
simon
The article seemed a little short for me, but then I am actively trying to
select between Lua and TCL for some personal scripting projects. There are
many fine features with each language and few downsides, so the selection
process is hard. Of course, that's a nice problem to have.

TCL is ahead by a nose at this point with Unicode support baked in (vs. using
a library) and file system handling built in (again vs. using a library).

~~~
groovy2shoes
Tcl is an interesting little language as well, and the niche it was created
for is similar to the one Lua was created for. The biggest advantages that Lua
has over Tcl, off the top of my head, are speed and lambdas. Tcl's semantics
make it very hard to optimize because it is stringly typed (with some bytecode
and value specialization in the background, but with conversions between
strings and other values as needed).

Tcl's file system interface is definitely an advantage if you're trying to
avoid third party libraries. However, depending on what you need to do with
Unicode strings, Lua's strings are "8-bit clean" and have no difficulty
storing Unicode characters; Lua's string _functions_ (the pattern-matching
functions in particular) aren't Unicode aware.

~~~
bch
Tcl has lambdas (anonymous functions): <http://wiki.tcl.tk/4884>. As of 8.6
(currently in beta), it also has coroutines, and has a non-recursive engine
(stackless) among other niceties.

~~~
groovy2shoes
Shows how long it's been since I last used Tcl!

Still, Tcl's anonymous functions aren't quite what many people consider to be
lambdas:

    
    
        % set inc {x {expr $x + 1}}
        % apply $inc 1
        2
        % apply $inc 1
        2
        % $inc 1
        invalid command name "x {expr $x + 1}"
        % inc 1
        1
    

This works fine with `apply`, but if you treat it like a normal function, it
does some strange things. Conversely, functions that are defined with `proc`
aren't compatible with `apply` unless you wrap them up.

I'm not saying it's inadequate, just that the anonymous functions don't quite
work how you expect lambdas to work.

~~~
bch
I can't speak to what most people expect from lambdas; I force myself use
Tcl's [apply] occasionally just to try slightly different paradigms, so I
appreciate your commentary.

One thing to note though, your final [inc 1] has nothing to do w/ $inc. In the
interactive REPL (which I'm assuming you used), Tcl will (by default)
essentially autocomplete commands if it can, and [inc] completed to [incr],
which is "increment". [incr] adds (by default) 1 to the named variable and
returns its result. In this case, the variable name happens to be "1", later
accessible via "$1", or [set 1], for example.

[edit: I erroneously initially described the "1" in [incr 1] as the integer
constant 1; @groovy2shoes reply below reflects my original error. This does go
to show another neat feature of Tcl: no keywords.]

~~~
groovy2shoes
I didn't know that tclsh autocompletes commands; that's pretty neat. In this
case, it looks like [incr 1] is incrementing a variable called 1, and appears
to start from zero if the variable isn't initialized.

I find Tcl's command model interesting because it leads to a very tiny
semantics. A few years ago I spent a lot of time thinking about how it could
be extended to have lambdas, and I couldn't come up with a way that wouldn't
break the command model in some way or another. They aren't something Tcl
_needs_ to have, I just thought it'd be convenient. (Tcl's evaluation model
allows you to simulate higher-order procs, which, along with `apply`, covers
many use cases of lambda).

~~~
bch
Ya -- interactive tclsh has a few creature-features. The autocomplete we're
discussing, automatic fall-through to exec as if via sh(1), command history,
history editing, and perhaps more I'm forgetting.

    
    
      kamloops$ tclsh8.6
      % info commands up*
      update uplevel upvar
      % uptime
       7:17PM  up 1 hr, 7 users, load averages: 0.06, 0.12, 0.17
      % ls fu
      ls: fu: No such file or directory
      child process exited abnormally
      % ls -ld fu 
      ls: fu: No such file or directory
      child process exited abnormally
      % ^fu^foo
      ls -ld foo
      -rwxr-xr-x  1 joe  users  7300 Mar 23  2011 foo
      % history 
         1  info commands up*
         2  uptime
         3  ls fu
         4  ls -ld fu
         5  ls -ld foo
         6  history
      % !2
      uptime
       7:20PM  up  1:03, 7 users, load averages: 0.13, 0.12, 0.16

~~~
groovy2shoes
> automatic fall-through to exec as if via sh(1)

That explains why X11.app launched that one time I forgot a `$` before my
`x`...

~~~
bch
That sounds likely. Note that is strictly for interactively typed commands.
Witness:

    
    
      kamloops$ cat ls.tcl
      #!/usr/pkg/bin/tclsh8.6
    
      ls foo
    
      kamloops$ ./ls.tcl 
      invalid command name "ls"
          while executing
      "ls foo"
          (file "./ls.tcl" line 3)
      kamloops$ tclsh8.6
      % source ls.tcl
      invalid command name "ls"
      % ls foo
      foo
      % 
    

Now, back to your regularly scheduled Lua topic :)

------
bitcracker
I was first disappointed ... then amazed!

Disapointed because the author's link to the benchmark website lead me to the
wrong impression that Lua would be almost 30 times slower than Java 7. Then I
googled around and discovered the awesome LuaJit which seems to be able to
compete even with C++ in performance.

What I really like is Lua's code density (see samples in the Shootout's
benchmarks). Very impressive!

[http://shootout.alioth.debian.org/u32/benchmark.php?test=all...](http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=lua&lang2=java)

As an old LISPer and Schemer I would like to know if Lua Macros are really as
expressive and powerful as Lisp macros. Some people claim this but I am not
convinced (I would like to be convinced). The expressive power may be
theoretically equivalent but this is also true for C and Assembler :-) The
question is: Are Lua macros as easy to handle as Lisp and Scheme macros?

[http://stackoverflow.com/questions/323346/what-can-lisp-
do-t...](http://stackoverflow.com/questions/323346/what-can-lisp-do-that-lua-
cant)

------
pheon
The reason its not so popular? IMHO because we live in a society that favors
1sec landing pages, customized per individual options, complexity that rivals
air skyscrapers and shrinked wrapped ready-to-go solutions. This is not LUA.

LUA is just one tool in the tool box - its not the tool box.

------
Hexx
On the integration front, one thing I will also add is that in .NET
integrating Lua with your program feels pretty close to being a first-class
citizen. Very nice.

------
meric
In lua, the _metatable_ is the killer feature that python doesn't have.

~~~
hythloday
Could you explain what you can accomplish with Lua metatables that you can't
do with python __eg__ methods? I've only seen them used as a way to implement
operator overloading.

~~~
sshumaker
__index and __newindex are the key ones - effectively equivalent to
method_missing in Ruby. __index gets called if you try to read a non-existent
key, and __newindex gets called if you try to write to a non-existing key. You
can use these methods to implement inheritance, proxies, getters/setters, all
sorts of stuff.

~~~
hythloday
This sounds very much like Python's __getattribute__ [0] method. Is there a
difference I'm not understanding?

[0]
[http://docs.python.org/reference/datamodel.html#object.__get...](http://docs.python.org/reference/datamodel.html#object.__getattribute__)

~~~
sshumaker
I'm not that familiar with Python, but can you use __getattribute__ to provide
methods as well? Using __index is the way you typically implement inheritance
in Lua.

~~~
timtadh
yes.

    
    
        >>> class A(object):
        ...   def __getattribute__(self, key):
        ...     try: return object.__getattribute__(self, key)
        ...     except AttributeError: return lambda: 12
        ...
        >>> a = A()
        >>> a.asdf
        <function <lambda> at 0x7fbb8fb6f848>
        >>> a.asdf()
        12

------
forrestthewoods
If you want fast Lua I'd recommend checking out Havok Script
(<http://havok.com/products/script>). Technically it's not Lua, but rather an
extremely fast virtual machine that is compatible with Lua. I worked with it
when it was Kore prior to Havok's acquisition, but it was substantially faster
than the base Lua. It has some excellent debugging functionality as well.

No idea what it costs these days, but if you're writing Lua code and it's need
to be fast I'd recommend checking it out.

------
Angostura
For anyone with an iPad who wants to tinker with Lua, there's there really
rather nice Codea. <http://twolivesleft.com/Codea/>

------
johnx123-up
Ask HN: 4-Lua JVM implementations, which is best?
<http://news.ycombinator.com/item?id=3536996>

------
munchor
The worst problem with Lua is that arrays start at 1. That is way too bad for
me to use it. I only use it to configure Awesome WM, but it sucks for
everything else IMO because of "tables" starting at 1.

~~~
aeturnum
I've done a lot of work in Lua and haven't really found it to be an issue. As
long as you stick to doing things the "lua way" (i.e. pairs / ipairs), the
specific indexes matter very little. Every once in a while I'll have an, "oh
yah," moment where I use the wrong index and something doesn't work, but I
don't see how it's a deal breaker for anyone.

There are many features of Lua that have caused me more problems (the somewhat
inconsistent string conversion, for instance).

