The Peterman Pod - Creator of Lua: Scripting, Programming Languages, Predictions | Roberto Ierusalimschy
Episode Date: August 3, 2026Roberto Ierusalimschy is the creator of the Lua programming language. I interviewed him about Lua's unique strengths, programming language design and predictions for how AI will impact programming... languages.• My ergonomic keyboard project I mentioned, you can follow along here: https://read.compose.llc/• The Kickstarter page for it: https://www.kickstarter.com/projects/ryanlpeterman/compose-simple-ergonomics-beautifully-donePodcast links:• YouTube: https://youtu.be/jCZnFKk6M9A• Apple: https://podcasts.apple.com/us/podcast/the-peterman-pod/id1777363835• Transcript: https://www.developing.dev/p/creator-of-lua-scripting-programmingThank you to this episode's sponsor for supporting my work:• WorkOS: makes your app Enterprise Ready with easy to use APIs to add SSO, SCIM, RBAC, and more in just a few lines of code, check them out at https://workos.com/Timestamps:(00:00) Intro(00:43) What sets Lua apart(08:35) Comparing Lua with Python(13:04) Top book recommendation on language design(14:20) How JIT works and why it is hard(23:21) Compiling Python and interpreting C(30:31) How cross language calls work(36:58) Lua unique design decisions(51:17) Predictions for AIs impact on languages(01:00:10) Top 3 languages to learn to become a better engineer(01:03:21) Advice for his younger self(01:04:19) OutroWhere to find Roberto:• Website: https://www.inf.puc-rio.br/~roberto/• Wikipedia: https://en.wikipedia.org/wiki/Roberto_IerusalimschyWhere to find Ryan:• Newsletter: https://www.developing.dev/• X/Twitter: https://x.com/ryanlpeterman• LinkedIn: https://www.linkedin.com/in/ryanlpeterman/• Threads: https://www.threads.com/@ryanlpeterman• Instagram: https://www.instagram.com/ryanlpeterman• TikTok: https://www.tiktok.com/@ryanlpetermanReferenced in this episode:• The Evolution of Lua: https://www.lua.org/doc/hopl.pdf• LuaJIT: https://luajit.org/• How much does it cost: https://www.youtube.com/watch?v=EUvgoxBm7uc• JavaScript: The Good Parts (not an affiliate link): https://www.amazon.com/dp/0596517742
Transcript
Discussion (0)
It's completely feasible that you won't have programming languages.
This is Roberto, the creator of the Lua programming language,
and I asked them all about programming language design.
C++, I think, is a good example of a language that it's really, really complex.
JavaScript, I think, is even worse.
I always joke that the JavaScript, the good part,
a very thin book, comparative, the official JavaScript boost.
Given how much AI has been progressing, would you still recommend people learn computer science today?
If you really think about that, it's really difficult to recommend people learning anything.
Here's the full episode.
In 2023, Lua was the second highest programming language by growth, according to contributors on GitHub.
And I saw that it was also used in famous games like World of Warcraft and Roblo.
And so I wanted to ask you, what kind of programming language is Lua and what sets it apart?
Lua is a language that usually use together, combined it with another language, like C or C++.
And then you have an architecture where Lua takes care of the more dynamic part of your program,
things that change more frequently, things that are not so resource-intensive.
the hard parts you have written in C or C++.
So it's typically what is called the scripting language.
There is some confusion, I think, between scripting languages and dynamic languages.
And people just, I think, consider a dynamic language to be more or less the same thing as a scripting language.
And they are not exactly the same thing.
So, for instance, a big difference between Lua and several.
other scripting languages is that for scripting you have two typical uses. You can have the
that I call who has the main loop. So you can have the program written in C and calling Lua or you
have your program written in Lua calling C. And for several called scripting languages are actually
you don't have to, but it's much more easy to use if you have your program written in the
scripting language and the C language is only for your libraries. And Lou it's very good fit when
you want the reverse. You want the program written in C and then you have, it calls Lua from time
to time. So the point is that Lou, it's very good at this that you have the main loop,
the program written in C, and then it calls Loua for some tasks or for whatever you want to do.
And for instance, in games, this is very important to keep the frame ratio of the game.
So for instance, you have the loop, the loop keeps the rhythm of the game and keeps everything.
and then at every frame it calls Lua, Lua updates, all characters, all images, everything in the game,
and then it returned to see, to do their renderization, et cetera.
So it is a very good fit.
But the main point is that, the people sometimes call this the embedding versus extending.
So you can extend the scripting language you see, or you can embed the scripting language.
with C or you can embed the scripting language into C.
And so several languages are very good only for extending,
while Lua is really good for both embedding and extending.
Why is Lua good for embedding?
And Python, it's almost the opposite.
Because Lua since the beginning, Lua, we thought about Lua as a library.
Since the beginning, Lua was written
as a library. So I think that's the main difference. Lua has a standalone program that I mean you can
call Lua in your console, in your common line. But that program is just a client of the official
client of the library following the same API that any other program can use. So this idea of
language as a library, I think it's not very common. It's something that is very particular in Lua.
When you design a language as a library, what are the unique, I guess, design decisions?
I think that goes a lot of small and big details.
For instance, your idea of what is your global space, about scopes of variables,
about exception handling, for instance, it's very important.
It's very common in lieu that you raise an exception.
in lure, but you catch the exception in C.
So all these things about how you do exception handling in the language.
Another, it's not a big deal, but it's for instance, most dynamic languages,
that's almost a definition of a dynamic language.
They have an Eval function that you can give a piece of code,
and then it executes that to code.
In Lue, we don't, instead of Eval, we have a function that we
called load that you give a piece of code and it returns a function, an internal function,
like it was a lure function, that when you call that function, then you execute the associated
code. It doesn't execute immediately. So you have this clear separation between compiling,
like the lure code that you have, and then you can do that in C. So on some,
you can get a piece of Lua code, you can compile it, check if it has errors, etc.
Then you call that for, for instance, a different piece, or you can even call several times.
You can load functions from Lua into C.
You keep them, I mean, in the Lua space, and then you can call that same function again and again.
It's not a big difference, of course, because if you have Eval, you can.
evaluate a function declaration and then returns that function. So you can, if you have
Eval, you can do load. If you have load, you can do Eval. But I think load, it's simpler
to use for that kind of thing that is when you think about libraries. In Lua, it doesn't
have a global state. I think that's a, I forgot that, that's a very important difference.
When C starts, the first thing it has to do is to create a new Lua state.
And then everything you do, you do on that state, and that state is completely independent of everything else.
So C can, for instance, create another Lua state, and both states are completely independent.
completely. There is no communication between them.
And so this again shows that if and so for instance,
C can use a state to do a lot of stuff and then it can close the state
and all memory used by Lua is released.
Everything that Lua was using is released.
For instance, if C doesn't need to use Lua anymore for a problem,
you release all all resources used by Lua in your program in C
continues and then later it can again create another state, etc. So there's, as I said,
there is several small or not so small decisions in the language, but all the time we think
about the language as, is that good for embedding? Is that possible to do embedding and things like
that? When you think of the programming community generally, everyone is quite familiar with Python,
but not as familiar with Lua, I thought it might be interesting to compare the two languages.
So if you compared Lua to Python, what are the pros and cons of each language design?
Lua is a language that is intended to be used in this idea of scripting architecture.
So the Lua, for instance, it doesn't thrive having a lot of different libraries.
If you have something that, oh, I want to write a quick program for something, that Python is much better.
It has all the libraries you can dream about it.
It has a lot of libraries built in already into the language.
So the language is huge.
I mean, the installation is a huge download, etc.
But it has exactly, oh, I need that.
Oh, it's there.
I need that.
It's there.
And Louie is almost the opposite.
Some very minimalistic language
because the idea that you embed
Lua into your program, it
doesn't use almost any
resources. Most of the libraries,
the important libraries,
that you will use.
We'll be provided by the program itself.
It will be the comments like
and move a character or do some speech
or things like from the
engine of the game.
For instance, if you think about games,
but whatever, it is.
I think that's the main big difference.
They have very different goals.
I saw some benchmarks and I saw that Lua is much faster than Python.
Why is that?
Those benchmarks are not exactly,
but I think that the main point is exactly the one thing is that Lua does have
this focus on performance again in the realm of scripting language.
doesn't want to compete with C or C++,
but in the wheel of dynamic,
mostly now it's dynamic language,
not scripting languages,
we have some focus on performance.
So I think this is a first difference.
Python is actually much more,
I think it's a decision that they make.
Performance is not that important.
It's more important to be flexible,
to be easy to do whatever you want to do.
In Lua, sometimes we do not put some features
because we think that there is no way to implement that efficiently.
But also I think some part of that performance difference
comes exactly because of the size of Lerun.
So most of the virtual machine fits in your cache, for instance,
I think there is these two big things.
One is that Rue doesn't have so many features.
It's not so dynamic as Python.
So in Python, there is a lot of interactions.
because everything can mean something else.
In rule, we are a little more conservative on that side.
But I think also this thing of being small also makes it naturally faster.
So on the distinction between scripting languages and dynamic,
or I guess it seems like dynamic language is a superset,
scripting language is a subset of that.
And my understanding that JavaScript is a dynamic language,
not scripting language from your perspective.
Yes, exactly.
Yes, exactly.
Because it's scripting, it came.
The original scripting language was bash or the shells from Unix.
Of this idea that there's a language that coordinates other stuff.
So, for instance, it can be extending again.
You can use, but this idea that you have two different language,
the shell is only useful because,
you have a lot of problems written in C that are controlled by Shell.
So the scripting language has this very strong idea that you have this idea of a dual-language
architecture.
So sweetening is like the name scripting.
It means it's like the coordinator.
You give a script to be executed by those other things.
You gave a talk a while ago and someone asked you a question of, you know, what books do you recommend for, you know, studying programming languages?
And you said actually that you enjoyed studying the language design of other programming languages.
I like reading books that describe the design of the languages. I think the best books are those written by the author of a language about the design of that language.
What book recommendation do you think is best on language design?
JavaScript, the good parts, for instance.
It's kind of old now, but I think that I think it's a very interesting book,
although I always joke that the JavaScript, the good part,
a very thin book comparative, the official JavaScript,
it's like one hand of the language is the good part.
But I think that book is really interesting, because exactly it discussed the language.
It discuss even the bad parts and it focused on the good parts, but then explains why it's
there, why it was made that way, etc. That is a book that I like.
When we were talking about Lua, it sounds like one of the things that sets Lua apart is
the performance and how minimal it is. And when I was reading about Lua, I said,
I saw that there's Lua Jit.
How does the Lua Jit work?
Lua Jit, the first thing, it's completely different project.
It doesn't have anything to do with us.
But it's an incredible piece of software that is a just-in-time compiler for Lua.
And I think exactly one of the reasons it works so well on top of Lua
is because of the simplicity of Lua.
It's a very regular language.
I mean, it has a very, as I said,
it doesn't have many exceptions
or too many interactions
or things that, so it's not
that dynamic.
I mean, everything can mean something
completely different.
So that, I think that gives a very good
language for a judge.
But the, the, the, Mike Paul is the name
of the guy that made the,
I think he's still working on that
on the first logite.
It's unbelievable his work.
What makes writing a JIT difficult?
The first thing that for me,
I don't want to get involved with JIT
is because it's machine dependent.
It's not very productive.
I mean, you drew a lot of work
and only works on that architecture.
And then, oh, I want to run in another architecture.
But, my, Paul, he created a kind of
a pseudo-assembler that he writes in this assembly
and then he translates that assembler
to real machine code of the different machines
so trying to unify the different architecture
so there is a lot of work but I don't like
I think architecture I like to study
but I don't like to work with
because I think it's very unstable each new version
they change that or they change that.
I mean, they change the ADA for something,
and then now the stack has to be aligned in some various particular way.
And so, of course, also to get that performance that he gets.
He made what's called a trace compiler.
The idea of a trace compiler that instead of getting a function
and compiling a function,
It works like any JIT that it tries to detect things that are executably frequently.
And so it starts what's called a trace.
It gets recording everything that the code is doing,
including function calls, etc., until it closes the loop.
And then it compiles that loop, including function calls, etc.,
everything in line.
it compiles that.
For that specific, for instance,
so that number happens to be an integer,
so it compiles the number will be an integer again.
And there is a lot of checks,
just check everything is as assumed,
and then it executes the loop.
And then it's very, very, very fast.
But anything that is different,
for instance, you call again that,
you call it frequently with integers.
Suddenly you call it.
suddenly you call to with a float, then at some part of the code it breaks the condition,
and you have to return to the interpreter part.
And I think that's one of the worst parts that you have to translate the state that it's all
compressed into register, et cetera.
For instance, you don't even have a call stack because you didn't do the calls,
you just inline it.
But then, oh, something went wrong.
Now you have to continue interpreting.
So you have to recreate the stack that you didn't create originally, et cetera.
So even to think about that, I have headaches.
Standard Lua is portable, but to execute on a machine,
it eventually gets converted into machine instructions somewhere.
Where in the stack is it eventually translated to machine instruction?
instructions. Lou is written in C, the interpreter is written in C, and then so you compile that
into machine code, the interpreter, the LUA code. Then the point when you get some, some, I mean,
the LUA interpreter code, when you get some LUA code, you do what it we call a pre-compilation,
that is we translate to an internal language, and then the interpreter is just a big link.
is a loop with a switch.
I mean, that's a very big simplification,
but in general terms,
a loop with a switch that gets instruction,
does a switch and see,
oh, this instruction,
the instructions are quite similar to a CPU.
Move that, but then instead of creating,
it executes that structure.
Move A to B, so it does a move A to B
and executes that and again repeats, execute the next instruction. So this is how an interpreter works.
And basically, so we pre-compile a loop. There is a compilation, but we compiled for this virtual machine.
And then we have this main interpreter loop that people call that just fetch hit instruction.
A jump is just a jump. You have an array of byte.
codes a jump or just go to that. You have a counter that tells where you are in this array.
A jump, you just update that counter. It goes to another position of that array where you're
going to. So it's like you emulate the CPU in software. It's written in C, the interpreter. This main
loop is written in C. So if you compile it in Linux, it will run in Linux. In a
X-86 architecture, it will run in that architecture.
If you compile that in the Mac, it will run in the Mac.
It's a C program.
Got it.
Okay.
And that's the part that's not portable.
And the C compiler handles that.
Yes.
Yes.
Yes.
All portability of Lua comes on top of portability of C.
How does JIT compare to ahead of time compilation in terms of performance?
Both ahead of time.
Any kind of compilation.
is easily, not easily, but can be 10 times faster than interpreting or even 100 times faster
than interpreting depending what you are doing. But 10 times is a very good figure. Between a head of
time and trace compilation, then depends a lot of what you are doing. After trace compilation is
particularly good for benchmarks because you're repeating it more or less they are very uniformed
you are doing exactly the same thing again and again and again so then trace compilers shine the
i mean this is the best they can do in real programs that's depends a lot but but but i wouldn't say
there is a clear winner between the two. I think depends a lot of the kind of problem.
Is it possible to write an ahead-of-time compiler for Lua?
Yes, there are several. I mean, I'm not sure if there is anyone on production quality,
but for research, et cetera, there are several. I have a student who wrote one like a master thesis.
ridiculous simple Lua compiler, a head of time Lua compiler or something like that.
Exactly.
It was just, it gets this upcodes and expands into C code.
And then you send that to a C compiler and then you have a head of time compiler for Lua.
And it gave like three, five times boosting performance.
very, very, as the title said, it's like ridiculous, simple compiler.
I always hear there's compiled languages and there's dynamic or interpreted languages, I guess,
but really that distinction is in the tool chain, not necessarily in the way that the symbols
are laid out on the source code. Like I could write a compiler or a program that takes in
Python code and then converts it into machine code.
And then I would have compiled Python.
And you can interpret C code too.
You can write an interpreter for C.
Yes.
But the main difference is exactly what it's easy to do.
For instance, as I said, one of their hallmarks of interpreted languages,
the vowel.
So if you want to compile the language and keep a vowel,
you have to have a compel.
compiler as a library of your runtime because you may want to compile things during execution.
This is the hallmark of a dynamic language.
So you can create code while running code.
So that part is that that's why much more often than not dynamic languages are interpreted.
But you can compile, but then sometimes
or some compilers do not handle eval at all.
They say, you can compile as long as our program doesn't have evolves.
So there is some restrictions.
And as I said, you can interpret C code, I mean,
but you be extremely slowly.
It doesn't, but.
I think one big difference, when I look at statically,
or static language is a compiled language,
which is they seem to have type systems in them or the type annotations.
What is the role of a type system in the compilation process?
Depends a lot of the on the type system.
Several type systems like in C, for instance, are written to be an very important part of the compilation process.
So if you have the right type system, it's much, much easier to write a compiler.
A trivial example is one space for variables, because if you know, oh, this is an integer, this is a float, this is a double, you know exactly how many bytes of memory you need to that.
Otherwise, it's a mess. More often than not, you have to keep everything in the heap dynamically allocated, and so huge penalty in performance.
And for instance, when you see, as I said, a trivial, you have an addition.
A plus B.
If you know the type of A plus B, you have the type of A, the type of B, you have a compile time.
You know, all this plus is a, I'm adding two integers.
I just generate the machine code to add integers.
And there everything is fine.
In a dynamic language, I see a plus, I compile to a virtual language.
language is just a plus, but then how do I, at runtime, you have to check what is a,
oh, A is an integer, B is a float, oh, yeah, I have to convert or B is a string, or depending on
the language, if you're not doing addition, it can be doing concatenation or you can just
calling someone, and you have to do all that at runtime. So types can be very, very important
to compile efficiently, but
of course you have to have a type system that there are several languages now like a type script
that the types are kind of you do not guarantee that everything has the types you said they have
so then it's impossible to use them to compile because oh probably a will be an integer but
if it's not I mean it's if I have an integer register to boot
It must be a rest or things do not work.
But if you have the right type system, they are essential for a good compilation.
I know some programming language just have type inference.
What if you did, you ran type inference and you got an unambiguous set of types and then you
use that in compilation? Could you do that for Lua?
No.
not computable, but a lot of people try to do in type in inference for dynamic languages.
And it's a really hard problem and it's very difficult to do anything useful in terms of
performance.
What sometimes you get, but you have a very restrict.
If you write your programming that specific way, use, follow.
So it's like you don't have the type, but you write the program thinking about types.
And then if the problem is that very particular format, then you can do type inference and everything goes well.
Otherwise, either time inference doesn't work or, I mean, it works, but actually it infers very generic types for everything.
And so you cannot take advantage of all of the types.
Because exactly the dynamic nature of the language, this also happens with Lujit, for instance.
You can get much, much better performance.
If you have a kind of type system in your mind, usually we do that.
And you follow that type rules even without, I mean, the compiler, the language does not impose them on you,
but you assume, oh, I'm going to follow those.
some time discipline.
I'm not going to
use the same variable to store integers
and strings, et cetera,
and then you can have much better
results.
Open AI, Anthropic,
Cursor, and Versel
all use this product to make their lives better.
And the problem it solves
is when you're building SaaS or an AI
product and you want to sell to other
companies, there's all these requirements
you need to meet. There's SSO,
there's SCM, there's
R-back, there's audit logs. These are all things that take time to integrate, but aren't the main
focus of your app. WorkOS is an API layer that lets you meet all of these requirements in just a few
lines of code. So let's say you have a new SaaS product and you want to sell to other companies,
WorkOS will solve all of these critical feature gaps for you. You can check them out at
workos.com to learn more and get started. And I appreciate them for supporting my work and
sponsoring this podcast.
Earlier, you mentioned that Lua can call C and C could call Lua.
And you mentioned, we talked about the compiler and the interpreter and how did these
pieces work together in the case where you're chaining different programming languages.
Yeah, the main trick, I mean, it's not a trick, the technique for Lua calling C is C pointers.
function pointers, there is a pointer to a function.
This is part of the official C language.
So when you start Lua, suppose you are in C, as I said, you create a library.
You create a state, a Lua state, and then you can register.
You send to Lua C pointers, function pointers,
and pointers to functions in your C library associated with names it will stores that in some data
structure okay so it says oh the function sign is associated with that pointer etc so when it's
doing the interpretation oh this instruction is called instruction called let's see what it's
calling oh it's calling a what is the value of a oh it's a pointer to and then it
calls that pointer and then we did call the C function to do that.
And when C wants to call Lua, I mean, a Lua function is just a data structure from the point
of view of C, it's just an array of bytecoles of upcodes.
And then it calls the Lua interpreter function.
Please interpret that function for me.
So C can call Lua to interpret that function and that function is running and then can call a C function using a pointer.
And you can have that in the stack at several levels.
So we are running a Lua function that calls C and C calls Lua again.
And Lua calls C.
You have recursive stuff in that, et cetera, and everything works.
It just works.
And one of their talks on Lua, you mentioned that there's security benefits.
to using a scripting language?
What are those benefits and how does it protect the hardware?
It's not only hardware.
Once I gave a talk here in Brazil,
I was called it to give a talk in a Pi conference,
a Pi-Con, they called the Python Conference in Brazil.
They called me for a talk.
At the end of the talk, I said,
oh, Louis, we use it as a scripting language,
as I said, emphasizing that thing that you have these
dual language architecture. And I know of case of Lua being used with C++, we 4-plus-plus,
with several different languages. And then someone in the audience says, oh, we also use Lua for
scripting Python programs. And what's the case? They have a huge Python program for financial
stuff that has a do a lot of financial transactions, etc. And they, they, they have a huge Python program for financial.
wanted to do script, I mean, to have like a common line where you could write instructions
to be executed by the, at runtime, for instance, for debugging or for inspecting, for
whatever you need some kind of end user programming. But they said exactly what I was talking
about spaces. In Python, basically if you have a common line in you are going to run Python,
that Python can do whatever it wants to do in your program.
There is no way to protect it.
So if you gave that to the user,
the user could do whatever it wanted to do,
I mean, for the program.
So the program would break a lot of invariance
of a lot of important stuff in the files it kept, et cetera.
And so what they did, they gave the thinking,
Lua, because as I said,
Lua, you create a state,
For instance, as I just mentioned, you can only call C functions.
That is true in Python again, but with that particular date.
You can only call C functions if you give the C pointer to Lua.
So have a very strict, and there is very, as I said, there is a library.
When you create a Lue state, it has no functions at all.
There is nothing, I mean, you cannot open files.
everything there are we call standard libraries. Usually you open a state and you register
those standard libraries in Lua so you have the minimum like you have mathematical functions
etc. But it can open a state and has no functions at all in Lua. It can only do things
calling those specific functions you get. So they use Lua to have this kind of control. You can
write lua code here, but that law code can only do very specific things in the Python program.
You cannot call any Python function or, I mean, build any kind of Python data structure,
etc. So this is a nice example. In the case of hardware is the same thing. You cannot just go,
for instance, there is a port, a harder port that controls the speed of the fun.
that keeps the temperature of the CPU.
If you put that very low, you can really burn the CPU, I mean,
because the CPU gets very hot.
And so you have a C, you cannot call C directly.
You must call Lua, and only Lua has access to that.
So if you can only program in Lua, it's a dog, Lua,
then you check whether the numbers you are giving are precise or whatever it has to check,
and then it calls.
It's kind of like a sandbox environment.
Yes, exactly.
Yes, sandbox is the exact word for that.
I saw there was this, I guess, paper,
maybe it was an article you wrote on the history of Lua
with several other people.
I thought there were some interesting quotes in there.
I kind of wanted to ask you about.
So one of them, it says that there's this old joke
that says that a camel is a horse.
designed by a committee?
Yes.
That's not mine.
That's a real old joke.
Does that mean that you think
the best programming languages
are designed by as few people as possible?
Yes, I do see.
Yes.
Because one thing that it's easy
to observe is this.
If you have a committee
writing a language,
everyone wants
to put something from themselves into the language.
So you have that your favorite mechanism
and you will fight whatever it takes
to put your favorite mechanism into the language.
And very few people will fight against putting anything in the language.
Some people say, oh no, this is too much, this is too complicated,
but people fight much more fiercely for put something they'd want in the language
than against putting something in the language.
So when you have a committee, the tendency,
so let's keep adding stuff, let's keep adding stuff.
And people sometimes even do not understand,
I mean, you're not sure if everybody there is really know the language well.
I'm not putting that, but that fits with other parts of the,
oh, I didn't even know the language has this other part.
I mean, so things sometimes do not fit together very well, et cetera.
So first, you have what's called the conceptual integrity.
It's a name that gives that everything fits together, everything.
It's designed with everything else in mind, et cetera.
It's much easier to.
I'm not saying, I mean, Lua has several,
wrong stuff regarding because with time, etc., there you make mistakes.
But it's much easier to get things, right, if you have a small group of people that everybody
knows what everybody else is thinking.
I mean, you are deciding whether to put something in the language or not.
It's much easier to change your mind.
If you do not put something and then later you decide.
to add it to the language, then to add something and then later you decide, oh, I shouldn't
have, but that was not a good idea. So when in doubt our default is always, don't put it.
If you're not very sure, don't put it, we can always add that later and so keep the door
open to change your mind. I saw in the original Lua programming language that there was no
bullion type and I've never seen that before. Why was there no bullion in the original Lua?
Well, C doesn't have bullions. I mean, the original C and C 90 up to C 99,
they use integers. If it's zero is false, if it's different from zero is true.
And people lived quite well with that LISP and there are several
languages that don't have bullions. And actually, we only put bullions in Lua because we wanted
false. True is completely useless in Lua. Nobody used true. I mean, nobody is a joke, but it's too
strong. But it's not very useful. You can use almost any other value for true. But the problem is
that in lieu, that nil, that special value,
is in a table, it is equivalent to the key not being present.
You all think better that was a good decision,
but it's very embedded in the design of the language
and it has the strong concept that a table,
a key that is not present in a, in a table,
In a table, there is an associative array,
it has a new value.
It's completely indistinguishable whether it's absent.
I mean, absent means it has a new value,
nil valent means is absent.
So sometimes you want to have a false value,
but you want to know what it is there in the table.
And so we needed a false to have a false
you can put in the table and it's completely different
from being absent.
you know that is a key and the key has a false value. So we need a false value and if you are going
to have a false then we added true to make sense we have false without true. But the truth is
almost useless. Why not use zero as false if you're okay with one as true?
It could we could have used but that among other things that would be a big change because a
exactly it didn't was that way.
So we added that later in the language.
So changing zero to false would be a very big incompatibility.
But it could be, for instance, in Titan, I think a lot of stuff are false.
I mean, zero is false, empty list is false, empty.
In JavaScript, I think it's even worse.
I don't recall exactly, but I mean,
This is kind of arbitrary. I mean, you could have, for instance, nil, false, zero, empty string.
I mean, it just depends the kind of test that you use. It's not in dynamic languages. It's very easy.
Python has the, like you're describing, the truthy values and the falsely values. I guess they can be interpreted as false.
but it's more implicit, less explicit.
And I know JavaScript is even further on that spectrum
where you can do some really weird stuff that implicitly has some behavior.
Do you think that design direction is good or bad?
It's like a more compact, it's more easy to write stuff.
But you always have this balance in any language, it's almost anything.
The more flexible you, you,
the flexibility you have the less protection you have.
In C, you have something like that.
People do not notice because C is typed.
But you can check whether an integer is true or false.
You can check whether a float is true or false directly
because again it checks whether the float is zero or different from zero.
You can check whether a pointer is.
is nil or different from nul because in c null is a magic zero.
So it's kind of if you do not write any test,
it has an implicit test like different from zero.
And this zero can be an integer, can be a float, can be a pointer.
So in c also you have this kind of flexibility.
It's just that you have to be more explicit.
Usually these are avoids.
errors. So you have always this balance between easy to write and easy to make mistakes.
I saw that Lua is one indexed instead of zero indexed. And I had never seen a programming language
like that in my experience. There was a lot of programming languages like that. So, yeah, why is it
one indexed? Because everything in the real world are one indexed.
If you have a book, you have the chapter one, chapter two, nobody number chapters as zero,
one, two, three.
All the programmers are the only, even mathematicians, if you've got a mathematics book, a book
of mathematics, any sequence, it's A1 and A2, A3.
If you have a matrix, the first element is A1, A1, A12, and then A, everything is written
we thought only in programming language that is this idea of zero.
And the funniest part is that, for instance, Fortran,
that now it's very old language, but to index it from one,
in Pascal, you can choose, I mean, you write an array,
you can say this array is indexed from minus five to five.
And so it's indexed from whatever value you want to whatever value you want.
Zero became extremely popular because of C.
C used zero and a lot of languages copied,
are kind of inspired by C,
they have the same operators,
the same syntax for expressions.
The Boolean operators, for instance,
that is not standard mathematics.
Almost all languages chose the same operators
as they are written in C.
And so a lot of language copied C and then zero indexed became very popular.
And what it's funny is that in C, there is no indexing.
In C indexing is just an illusion because what you have is pointer arithmetic.
And C when you write A indexed by I, actually what you are saying, get the contents of A plus
why. And so because in seed you don't have indexing, you have displacements or deltas, I don't know
offsets, then it must have indexed by zero because of the, because then the first element
is the element that is at the original address. So C doesn't have indexing. So when you say
it's indexed by zero, it doesn't index by zero because it doesn't index by zero. Because it doesn't
indexed by anything.
But it has this illusion of indexing
and then it's easy to sing that.
And then a lot of language
that do not use pointer arithmetic,
do not have this restriction,
do not have these semantics,
copy it C
and cap the zero indexing
as this thing.
If you get a 12-year-old
and try to explain to them
zero indexing,
I assure it's much,
much easier for them to write, oh, I have a list of the first element.
I always joke that the first element is zero.
And you write first you for one, but the first element one is not one is zero.
So it has advantage of zero.
For some specific operators mathematically, for instance, you want to do a circular buffer,
zero is better.
There are some small advantage,
but it's much, much more confusing.
And as Mua has this idea of end-user programming,
we always joke, it's much easier to make life easier
for the non-programmers.
And I am sure that programmers can program whatever index they have to do
because they are supposedly they are professional.
They can learn that all indexing reform.
Then to put on the end user the burden of using something completely different from them indexing by zero.
What does this mean the element index zero?
And I never saw the chapters in the boy.
Yes, the first chapter is at zero.
The second chapter is at one.
No, I'm not joking.
When you try to explain that to non-programmer, even don't.
Then they need to be 12 year olds.
I mean, just get anyone that is not.
And the programmer think, oh, I have the apps.
You're grown up.
You are, I mean, okay, you are a question.
You are with zero.
I'm sure you can learn to program if one or minus one or whatever it is the base you have to use.
I'm sure.
But do you think you see a lot of bugs?
Because maybe someone thinks it's zero.
Unfortunately, I see some bugs, but as I always say, that are the kind of bugs that just shows that you didn't do minimum testing.
Because that kind of bug is not a kind of that kind of bug that always if you try to, anything you try to do in an array.
if you start from zero or start from one, you have a bug.
So the most simple test that you can imagine to test anything related to an array,
to a list, et cetera.
And if you mistake zero to one, you detect.
So if you have that kind of bug, it just shows that you didn't test that code at all.
There was this talk that you gave on the cost of adding language features to Lua and how there's a lot of hidden costs.
And I think today, implementation costs of software is going down due to, you know, AI code generation or LLMs.
And I was wondering if that changes your thinking on, I guess, the cost of adding features to a programming language.
AI is something that we don't really know what it's going to happen.
If you go to an extreme, it's completely feasible that we won't have programming languages.
Because if the AI is writing all your code and is checking all your code and doing everything,
in a few years maybe we don't need programming.
I can write machine code directly.
It doesn't need programming languages.
It's easier for them to compare or even generate the code directly.
I mean, I don't know what's going to happen in a few years.
So I think it's very hard for me to talk anything about AI
because I have, and I think nobody have a clear idea.
what, I mean, people have
a maybe idea what it happens
in one year or two years,
but in five years,
I mean, anyone that says,
oh, that's going to happen in five years,
it's just, I mean,
just guess.
So,
I think it's hard to say
anything. This is all
because of AI.
So,
keeping the
minimum thing, I mean, that still
have, for instance,
why you still use programming languages
because you want the user
or some human
to be able to check the result
of what the AI is doing,
etc. So I
still think that most
of the things about programming language
still hold. For instance,
the cost of complexity
of you understanding, I mean,
I create a code for you
and then you really understanding
what that code does.
I mean, it's even worse, I mean, it's much more important that the language should be clear and has no hidden mechanisms, because the AI may use a hidden mechanism.
It doesn't have the concept, oh, that will be difficult for a human to understand that what is really happening here is something that, something that, for instance, oh, I can use that, but I'm for sure it's going to put a comment here.
because I'm sure that someone that reads that in one month,
it's not going to understand.
EA doesn't have that kind of thinking.
And so just use that trick or that thing.
And so I think if you think about this idea of AI generating code,
I think it's even more important for the language to be simple,
to be understandable for you to be able to really understand that the code
that the code that you have seen does what you think it should do it.
You really understand what the code is doing.
So this thing about simplicity, I think it's very important.
And I think the other parts from the need, maybe I may facilitate documentation.
I'm not sure if I mean this thing about conceptual integrity, for instance,
to keep things, oh, that makes sense, et cetera.
I really think one of the main costs is that it's the burden you put on the user to learn
one more thing about your language.
So there's the other cost.
I have said that implementation is the part that AI can really help you.
It's not a really important cost.
If you think about like a spectrum of simple to complex,
what programming languages are, you know, the most simple ones that you think of,
that are easy to understand less confusing side effects,
and what programming languages are the most complex and have the most footguns?
This famous quote also, I don't know from whom,
that the simplest possible, but not simpler than that,
because if you go to the extreme of simplicity, you could get, for instance,
Lambda calculus or Turing machines and said, oh, that's really simple. I mean, this is really
simple, but it's completely impossible to write any programming in that. I mean, if you have
really simple stuff, I think the extremes will be like that, but you don't want to be there.
But for the other side, I think C++, I think is a good example of a language that I think
it's really, really complex. A question that comes up a lot is,
Given how much AI has been progressing, would you still recommend people learn computer science today?
If you really think about that, it's really difficult to recommend people learning anything for a profession.
I mean, we have no idea what AI will do in five years. If someone is entering university now,
they're going to graduate in four years, five years, or at minimum three and a half years or
then nobody have any idea what the world is the world you stay there your profession will be like in four years from now.
So it's really hard to, I mean, to say, oh, yes, you can still going to, I mean, because now people say, oh, no, the manual tasks, the AI is very good, but you need the whole architecture.
you need like a software engineer to do to see the big picture, etc.
That is now, but you have no idea that will be true in four years or five years.
So I think, I like, I enjoy programming.
I could do, I mean, some people say, or use AI for that.
I mean, I probably because I like that.
So choose something that you like, but really for us, you're really thinking, how am I going
to live with that, I have no idea.
It's really, I think it's a really hard time
to be choosing the profession.
I mean, you've worked on Lua for such a long time.
When you look back on it, what went well
and what didn't go well?
We had this privilege of not having to satisfy clients.
So we all did not have, as I said, for instance,
You can choose to add some feature to the language because you do not have a pressure.
Oh, we need that feature, that feature, whatever it takes or etc.
So we have this privilege of, oh, we are not sure whether to put that.
We don't put that.
You can wait one year or so I think that it's much easier to do a good project, a beautiful project.
So I'm not sure this is a recommendation.
try to work without much pressure.
People usually do not have this choice.
What was your measure of success if you're working on a programming language?
Like, you know, how did you know it was good?
It's more important to sometimes that good people that I recognize as we like the result
than a lot of people that I have no idea what's there.
who they are, et cetera, like.
So I think this metric of quantity,
that is the standard metric nowadays in the web,
it's got much worse,
that everything is just in the number of follows
that me doesn't care who is following you,
just as many people as possible.
So sometimes for me it's much more important
if someone that I really admire of things
of this, that say something good about Lua,
then oh, we have that many,
but of course this would also to have some number of users and to be recognized
but I think it's a balance between all of this.
Do you recommend people study other programming languages to get better at programming?
And so the question is, what are the top three programming languages that you think
every engineer should learn in 2026 to kind of become better at programming?
Haskell, I think, is incredible language.
It has everything you need to really learn about functional programming.
I think one of the main benefits is much, there is an old joke in the Haskell community
that if you write a program in Haskell and in C,
In C, we'll spend one week to make it efficient,
and then you will spend one year to make it correct.
In Hasker, you spend one week to make it correct,
and then you may spend one year to make it efficient.
Again, this is not my joke, but it has some truths,
not always true, et cetera, but I think it gives the idea.
I think this is maybe the, the,
main, the most important lesson of Haskell.
But Haskell has many other, this thing about type inference,
for instance, that the entire language is, types are optional everywhere,
and yet it can do type inference for everything.
It can infer the types correctly, et cetera.
C or some low language.
I mean, you can also have a,
to learn some assembler or I mean to see you.
But assemblers now are becoming too much complex.
It would be to learn like the 80-80 assemble,
very old assembler of a very,
but to have exactly this idea of what a machine does,
how it does stuff, exactly the basic level,
to have this understanding.
Skin is a language that I like very much
because of this, exactly this economy of ideas.
There are very few concepts and you can do some amazing things with very few concepts.
One language that is very, very, very old, but I still think it is snowball.
I think it was the first language is to have pattern matching in this idea of doing a, I mean,
it's really strong patterns, et cetera.
And I think it's sometimes it's interesting to see all.
languages because exactly nowadays a lot of languages tend to like I said zero indexing that people
they copy a lot they tend to be true uniform in some aspects and it's interesting to see some
older languages that have some ideas that may maybe not even good ideas but it's interesting
last question for you is knowing everything you know now if you could
could go back to when you had just started your career and give yourself some advice,
what would you say? To know a lot of stuff, you really have to study a lot of stuff.
It takes time. I also joke about that. People say, oh, learn Lua in 30 minutes,
or learn Python in five minutes or, and I always say that they wanted to learn programming
in five years.
That's really
take time. You have to learn that.
That is a lot of stuff to learn.
There's no magic.
There's no.
You really have to learn a lot of different things.
Thank you so much for your time, Professor.
I really appreciate it.
It was a lot of fun.
Thank you.
My pleasure.
Hey, thank you for watching this podcast.
If you liked it and you want to see the show grow,
please support with a comment or a like.
Also, if you have any recommendations for people you want me to bring on,
please drop a comment.
Guests like Barbara Liskov, Mike Stonebreaker, Mark Brooker,
these were all people that I brought on because someone left a comment.
On another note, aside from the podcast,
I'm working on building the ergonomic keyboard that I wish existed.
Here's a glance at the prototype.
It's a split keyboard.
So there's two sides.
This is in the case.
But yeah, we launched on Kickstarter.
and we hit our goal within eight hours of launching.
I really appreciate it if you were one of the people
who grabbed one of the early units.
We're now working on the long journey
of building the tooling now.
And so if you still want to pick one up,
I've left the late pledges open on Kickstarter.
So you can grab one there.
I'll put a link in the description.
Thank you again for watching the podcast
and I'll see you in the next episode.
