Alright, so let's get started. Thank you for sticking around during lunchtime. This is
going to be five years of till, minimalism versus growth in language design. Okay, here
we go. Okay, quick introductions. I'm Hisham. I've been doing free software for a long time
with involved in many projects. I work at Kong where we do free software like free
open source API gateway using mostly Lua. I'm currently working on the team that's
having web assembly support in Kong and some of my other projects are LuaRocks,
package manager, Google Linux, the weirdest distro ever and Htop, the process monitor.
So, but here I'm here to talk about like the project that I'm most recently excited about,
which is till. Till is a statically typed dialect of the Lua language. Right, so if you know like
what type script is to JavaScript, you can think it's the same, right till is to Lua,
what type script is to JavaScript, but let's not go too far with that analogy because here we're
trying to keep to Lua's spirit, which is like a very minimal, a very tiny language and like I
don't have the backing of Microsoft and hundreds of developers working on as they do on type script,
but essentially we have a compiler, till that outputs Lua files. And so here's a quick taste of
what till looks like. This is just like a random function I picked like from the source code of
the latest version of till that I'm working on. And so what's lighter here like is what is not Lua,
essentially the parts of till that are different from Lua. So we have a couple of different
operators, you can add types there, but otherwise as you can see it's it's mostly regular Lua.
I made the mistake of talking about till before without showing lots of search code. So this time
I'm gonna make sure I show source code till is like the epitome of like conference driven
development because when I first had the idea I started like hacking it together and like when
I first presented it like was the challenge like can we do this right? Can we add types while
remaining minimal and when I presented it back in 2019 like I was like halfway through like the
compiler student compile itself and I show like oh I started like 500 errors and I'm currently like
100 or something like that. But eventually I got it working and then the next year I came back here
and show it to you and I said like minimalist type Lua is here and there's this weird title
because the language didn't have a name yet. So and then eventually at the third part of the
trilogy we had a name and we actually had users and had stuff going actually going on with the
language. But and then I basically said that well now I think I'm gonna get let it settle for a bit
so that people can actually use it because if the language keep changing syntax like all the time
and stuff like that like people won't feel comfortable adopting it right. So yeah so that's
what's be going like we have like this small community I always like to make a distinction
between like a community and a user base right because especially in the industry people like
to look at numbers so whenever people ask me how is still going like I tell him like oh we're like
1.8k GitHub stars which is like the vanity metric like that doesn't really mean anything right but
it means something right but in but in practice when I when I think about a community I think
about the people who are involved with it and then I could say like like oh there there are like all
of the other people who gotten involved right because I'm just doing the source-to-source compiler
right and then there's people doing the build system there's people doing like the VS code
plugin right that gives like IDE autocomplete those sorts of things so in nowadays for a language
that's that's part of the whole package that's what expected of a modern language right so if I if
I think on when I think of the two community I think about like I don't know like 10 people or
or even less right but the people who regularly discuss on GitHub and all of that so right that
that's the community right like the human aspect of it and speaking of community feedback here is
like this is a full screenshot of like all of like if you go through all of the issues pages
there are currently like if you open the the till GitHub repo right now there's like 67 issues like
these are all of them right and I one thing I hate about GitHub is that they call everything issues
right so like feature requests like back in the days of search for so we're like separate pages for
like bugs and feature requests right and out like calling a feature request issue I think it's like
super weird like I would like the program to do something that you did not design it to do now
your code has issues right it's like no so basically what I do I label all of them like so the ones
with the light labels here are feature requests and the ones with like the darker labels which are
like the red ones those are the bugs right so I currently have like five open bugs and like
three pages of feature requests right and and it's nice like sometimes you don't want to close
your feature request you want to keep them around so that other people who have the same
request can see and comment on them right so basically over time your job is going to keep
accumulated an endless list of feature requests you're going to look at the repo and one day
will have like 200 open issues oh this program must be all broken right no no it has a lot of
people who are very interested in it this is actually a sign of success like people are interested
in your program enough so that they are using it and asking for more stuff right so yeah so but then
once you have this many feature requests like and we're here talking about minimalism how to keep
the language small right I cannot add everything that people ask for and this is like my hobby side
project currently I don't even have the time even if I wanted to right but I don't want to because
I wanted to keep it small keeping to the like that idea from the very first talk like the challenge
was how to keep it small right and the challenging thing is like I can't add everything that people
ask for or even everything that people contribute because not only people go there and ask feature
requests some people actually send in features like all written like a spoil requests like like I
would like to do this extra thing and here's the code to do it please add it and I go like sorry
right but but it's super important feedback right so uh yeah but when you go go back like it's always
nice to look at that whole list and look try to look at the big picture right and then I saw like two
like very recurring themes on things that people were asking for like related about like one is
like nil safety right the famous uh billion dollar mistake right as as mentioned by touring award winner
like 24 when he talked about this uh saying like adding the concept of null to a programming language
was back in the day was his mistake because like everything that came out of that afterwards and
um and lua is another of those language this does has like a nil type right and all of the
consequences come with that uh and the other one is that people keep asking for abilities to express
more complex table types because lua is like every like the only single composite type that you have
like apart from like integers like like numbers bullions like and like tables right which is a
thing that doubles as a hash table and an array right like it's there's a thing with keys and values
and if you use numbers the the it has like some special behaviors to make an array access efficient
but otherwise just think of it as one big thing with keys and values but once you start talking
about types you look like oh this table is really an object this table is really a map this table is
really an array this table is really a a map except when you use integer keys then i wanted to
act as an array like these are kind of things that lua programmers do all the time because once you
have a table that accepts everything right you start having these composite types and all these
weird things and but then people mix it up right and those are the bugs that people run into when
they're coding in lua with no explicit typing and they would like teal to help them with that right
so let's talk about the first one uh a little uh so as i mentioned i was mentioning like
giving that every variable can accept nil and you can pass stuff around like that uh until
basically every type includes nil as a possible value right if you declare a variable as integer
you can still put nil in there like essentially every variable is like optional right and in that
sense so this has some consequences right this makes for example that uh in lua like you declare
a function to have like three arguments you can just pass one argument or no arguments and like
the lua vm will accept it and people do that on purpose because essentially they mean like oh in
the semantics of my my application that argument is optional right so uh so lua accepts that and
because lua accepts that teal accepts that right and uh another side effect is that in table like
missing keys are valid right so um people let's say you define a function that operates on a table
that has like x and y uh fields right uh but then your in your program since you decide
since you designed that function that just wants to take something that takes x and y you want to
pass other things right that have extra fields and sometimes they don't right so uh it gets it gets
really messy right uh so in one of the previous talks i mentioned about like that i started looking
at like doing the whole thing about uh implementing like nullability checks into the variables and
how like and i showed like the size of the teal compiler source code versus the size of like
all of the code to do proper reachability tests for null variables and everything and make like
the whole check super automatic and it started to get like bigger than the compiler itself uh
so that was sort of like a complete but heavyweight solution right so a very lightweight solution or
i would say lighter weight solution like then actually having the proper optional types that
people really want right was to have just arity checks which is like how many things you actually
put inside the parentheses when calling a function right so and yes if eventually we find like a
lightweight way to like nicely do optional types this will become sort of a redundant feature
but this is this is what it looks like right if you have a function that takes like
two parameters like if you pass two parameters then it's valid so if you just pass one parameter
this didn't fail before but it will catch the error now but if you pass two parameters and one of
them is nil well you know the arity of the function is still two so that's so that's valid right but
who will write this right so i mean it's very like 80 20 thing like it's a very simple thing that
catches like the kinds of mistakes that people actually do right so you have you kind of have to
be uh forcing to to to get into trouble with that so uh yeah but if you want to be able to do that
then you act you actually mark the arity like not in the type but in the argument right like the
the argument is optional it's not that the type of y is like an optional integer the type is integer
but y is an optional argument right so that's like a very simple to implement thing like that
i had it i can draft state for a long time and i just decided to put that in into the language
because it's always like oh do i want to add one more feature to the language right do i want to
because i was able to do like to write the till compiler in itself so with the features that
currently has you're able to write a compiler so like i go like okay the features look enough right
but people get asking for more features so but then like being possible and being pleasant is kind
of different i already feel like like coding in till in general because of the helps that type give
you already feels like more pleasant to me as a very in a very subjective way than coding in like
plain lua right but when i started working on the next feature like then i really wanted to have
this because i wanted to do big refactors and change the numbers of arguments of things and
i wanted the compiler to tell me uh if uh if i was making mistakes so i added this feature
feature for my own use and it already proved like useful enough and uh yeah so if we're doing that
for nil safety for for arguments what about uh for table keys can we do that it's trickier to
pull it off right because uh even if you want to say like oh this key is optional this key is mandatory
some one thing that people do in lua all the time is just like start a table with like open
closed bracket like this is an empty table and start filling the elements one by one so like
after the table is ready right that argument's no longer optional but it's optional for a while
and it's a very common pattern so um however uh since i had a feature that i created for my
own use of how i specify maps i adopted that for records as well so uh which is that total
annotation because like lua like modern lua has these annotations like const and and so i just
i don't want to say total which is for things like this right if you have an enum saying like
which essentially restricts your string type into a set of known strings right you can say that
the map that you're declaring here is total so the compiler will give you an error here because
you specified north and south but not east and west okay so uh right so essentially we did the same
for uh records right so uh you can specify a total record and for that use case of i'm declaring a
table and i want everything to be in it uh you can uh you can specify that again like it's a
lightweight solution then the whole solution but it's something that already gives you uh
you know gets you a long way um okay so uh just because we started late right how
how do how do we go on time like do i just keep going and then
right okay all right so uh yeah so then the second one which is like the more interesting one is like
subtitling table types i mean like i have avoided going with like complicated uh sub typing definitions
as as you start combining uh those kinds of features like you can you can go real crazy with
that like with even like features that programmers in type languages use every day like if you combine
like generics and sub typing like there are computer sign results that show you that you
end up with like a computationally undecidable type system and things like that so uh so i have
avoided like delving into this complexity for as long as i could so for that super common case of
i have this table which is a record in an array at the same time i added this jenki type that's
array record that's just for doing that uh and to avoid having to do sub typing and things like that
like and complex type hierarchies just because i wanted to have collections like i added like
invariant generics so you can have like list of t but you cannot specify anything about t
and then that worked and because uh typing and callbacks and passing like checking
function arguments for covariance versus contravariant and all that gets complicated
you just do bivariant matching you like you accepted both ways which is like
wrong like it's unsound by design right but it will at least prevent you from matching like
completely unrelated functions like you're not passing like the wrong function but
if you're doing the thing like in the correct ballpark it will catch it right so um yeah which is
some kind of like unsoundness by design that top typescript already has to do so uh yeah and one big
limitation that we have because we had union types but you cannot you could not have union
types of multiple table types right because at runtime the code that it translates to when you're
trying to check like which which value i have in this union type which is like oh it's a it's an
engineer or uh like my record like my object the luo code that that would generate uh became like
luo code that says like show check that the luo type is number or check that the luo type is
table and then it couldn't tell all the tables apart at runtime right so you will have to generate
code that actually checks the tables by their contents right so you can tell like is this a
circle is this a triangle is this like what is this right and turns out that in the real world
a luo programmer is like an existing luo frameworks that people would want to use with till define
their own object or oop like object-oriented systems with their own like inheritance systems and how to
how to declare like the the the type checking right people already do this writing this custom code
for type checking right but then the till compiler doesn't understand that right so uh for things like
this if i want to have the is operator to work nicely in till so that the compiler understand it
like i need to be able to translate that to that like framework specific way of determining like
what the type is right so since we had records before like the the next version of till is going
to have interfaces right so the interface like this was instead of writing record you write interface
right but now you can you can actually have subtyping from interfaces which are abstract
into records but then you have this fine where clause here which has an expression like it has
a bit of code with essentially is like when you want to do an is check this is the code that you
should use like it's essentially a macro right you have to replace this everywhere you need to
do that change right and now essentially you can do uh you can do union types as long as the all of
the types that you are putting in the union declare like there how to do the is operation right and
yeah we're only on time so yeah so that's essentially what i described there and the thing is that that
that magic where clause right essentially i had to add a feature to add a feature right because like
i'm really having i'm having i'm really having to implement like a macro expansion thing for
expressions just in order to have that work loss so like why not expose that but then again
i thought like oh so i need to add macros to the language no i just went lighter wait again i just
added macros for expressions and not like a full macro processor right which is what many projects
for lua have tried to do in over the years but one of none of them like have become established
right and turns out that where now it's syntactic sugar like we actually have like macro expressions
in the language right but it was motivated by that right so in short what happened like till
has seen use okay people want more features and less limitations which translates to many future
requests oh no right but many future requests they relate to the same pain points right so the idea
is that you try to combine them and come up with like the what's the most minimal design to try to
address the most of these pain points so the things that came up out of that were like optional
iris interfaces macro expressions and the idea was that i would just pick the lighter weight
solution right because whenever possible like just to try to like just harking back to the title like
minimalism of the language versus its growth right both the growth of the compiler the growth of
the language specification and the growth of the user base right so so that's the approach that i
took like you know you sometimes you have to choose like the incomplete solution just in order to
balance all of those desires right so yeah that's it what i had thank you for sitting around
thank you we need to free up the room for the next round but we can still have one or two quick
questions
Yeah, yeah.
So have you decided what to improve the meta programming
or doing some stuff, but what the meta tables and all that stuff?
Okay.
Have you ever decided for a new program or a new country
you know the goal with the LAT?
If I have some plan to improve the handling of meta tables,
meta tables, it currently does have support for meta tables
in records, you can specify them.
The checks are not very strict, right?
And I haven't had much feedback on that.
So like if people run into trouble, I look into it,
otherwise I'm just going to keep it as it is.
Right now you can use them and no one's complaining,
so I'm happy with that.
Thank you.