is a variant of load.) This function does
not execute a piece of code; instead,
it produces a Lua function that, when
called, executes the given piece of code.
Of course, it is easy to convert eval
into load and vice versa. Despite this
equivalence, we think load has some
advantages over eval. Conceptually,
load maps the program text to a value
in the language instead of mapping it
to an action. An eval function is usually
the most complex function in an API.
By separating “compilation” from execution, it becomes a little simpler; in
particular, unlike eval, load never has
side effects.
The separation between compilation and execution also avoids a combinatorial problem. Lua has three different load functions, depending on the
source: one for loading strings, one for
loading files, and one for loading data
read by a given reader function. (The
former two functions are implemented
on top of the latter.)
Because there are two ways to call
functions (protected and unprotected),
we would need six different eval functions to cover all possibilities.
Error handling is also simpler, as
static and dynamic errors occur separately. Finally, load ensures that all Lua
code is always inside some function,
which gives more regularity to the language.
Closely related to the eval function
is the concept of environment. Every
Turing-complete language can interpret itself; this is a hallmark of Turing
machines. What makes eval special
is that it executes dynamic code in the
same environment as the program that
is using it. In other words, an eval
construction offers some level of reflection. For example, it is not too difficult to write a C interpreter in C. But
faced with a statement such as x= 1,
this interpreter has no way of accessing variable x in the program, if there
is one. (Some non-ANSI facilities, such
as those related to dynamic-linking libraries, allow a C program to find the
address of a given global symbol, but
the program still cannot find anything
about its type.)
An environment in Lua is simply a
table. Lua offers only two kinds of vari-
ables: local variables and table fields.
Syntactically, Lua also offers global
variables: any name not bound to a lo-
cal declaration is considered global.
Semantically, these unbound names
refer to fields in a particular table asso-
ciated with the enclosing function; this
table is called the environment of that
function. In a typical program, most
(or all) functions share a single envi-
ronment table, which then plays the
role of a global environment.
Conclusion
We have argued that providing an API
to the outside world is not a detail in
the implementation of a scripting language, but instead is a decision that
may affect the entire language. We
have shown how the design of Lua was
affected by its API and vice versa.
The design of any programming
language involves many such trade-
offs. Some language attributes, such as
simplicity, favor embeddability, while
others, such as static verification, do
not. The design of Lua involves sev-
eral trade-offs around embeddability.
The support for modules is a typical
example. Lua supports modules with
a minimum of extra mechanisms, fa-
voring simplicity and embeddability at
the expense of some facilities such as
unqualified imports. Another example
is the support for lexical scoping. Here
we chose better static verification to
the detriment of its embeddability. We
are happy with the balance of trade-
offs in Lua, but it was a learning experi-
ence for us to pass through the eye of
that needle.
Related articles
on queue.acm.org
Purpose-Built Languages
Mike Shapiro
http://queue.acm.org/detail.cfm?id=1508217
A Conversation with Will harvey
Chris Dibona
http://queue.acm.org/detail.cfm?id=971586
People in Our Software
John Richards, Jim Christensen
http://queue.acm.org/detail.cfm?id=971596
References
1. de Moura, a., Ierusalimschy, r. revisiting coroutines.
ACM Trans. Programming Languages and Systems 31,
2 (2009), 6. 1–6. 31.
2. Deloura, M. the engine survey: general results.
Gamasutra; http://www.gamasutra.com/blogs/
MarkDeloura/20090302/581/the_engine_survey_
general_results.php.
3. Ierusalimschy, r. Programming in Lua, 2nd Ed. lua.org,
rio de Janeiro, Brazil, 2006.
4. Ierusalimschy, r., de figueiredo, l. h., celes, W. lua—
an extensible extension language. Soft ware: Practice
and Experience 26, 6 (1996), 635–652.
5. Ierusalimschy, r., de figueiredo, l. h., celes, W.
the implementation of lua 5.0. Journal of Universal
Computer Science 11, 7 (2005): 1159–1176.
6. Ierusalimschy, r., de figueiredo, l. h., celes, W.
the evolution of lua. In Proceedings of the 3rd ACM
SIGPLAN Conference on History of Programming
Languages (san Diego, ca, June 2007).
7. ousterhout, J.k. scripting: higher-level programming for
the 21st century. IEEE Computer 31, 3 (1998), 23–30.
8. Python software foundation. extending and
embedding the Python interpreter, release 2. 7 (apr.
2011); http://docs.python.org/extending/.
Roberto Ierusalimschy is an associate professor
of computer science at Puc-rio (Pontifical catholic
university of rio de Janeiro), where he works on
programming-language design and implementation. he
is the leading architect of the lua programming language
and the author of Programming in Lua (now in its second
edition).
Luiz henrique de Figueiredo is a full researcher and
a member of the Vision and graphics laboratory at the
national Institute for Pure and applied Mathematics
in rio de Janeiro. he is also a consultant for geometric
modeling and software tools at tecgraf, the computer
graphics technology group of Puc-rio, where he helped
create lua.
Waldemar Celes is an assistant professor in the
computer science department at Pontifical catholic
university of rio de Janeiro (Puc-rio) and a former
postdoctoral associate at the Program of computer
graphics, cornell university. he is part of the computer
graphics technology group of Puc-rio, where he
coordinates the visualization group. he is also one of the
authors of the lua programming language.
© 2011 acM 0001-0782/11/07 $10.00