The main thing you need to know is that Lua's table type can be numerically iterated between index 1 and the first gap where numeric index has nil value using the ipairs iterator in addition to the non-exclusively-numeric unordered pairs iterator. A common pitfall with sparse tables is that the length shortcut # returns seemingly the wrong result if you aren't aware of that first part.
Most of the difficulty writing in Lua comes from the fact that there's no first class support for OO-style Classes, so you have to fake them, and there's no standard library so you end up reinventing a lot.
But other than that, it's a dead simple language with few features.
Metatables are cool, but have some weirdness to them. For OOP i ended up using metatables to make a simple prototype(rather than class) based system, but it was hacky at best.
Tables themselves are pretty awesome and powerful, but I have to admit, working with them gets a bit tiresome in ways working with dedicated arrays and hash maps don't. You have to remember exactly what kind of data is in your tables and looping through them can be a pain.
Overall though, I still love lua, it's the language that helped me 'get' programming and I wouldn't actually appreciate dedicated data structures and typed variables so much if I hadn't had the experience of starting with a more free, loose and simple language like lua. Also, its ability to easily interface with C and be easily embedded has made it appear in so many different and sometimes strange and just downright cool applications.
I've been playing with the solarus engine lately, it uses lua for its scripting, it's the first time I've written any lua in a while, but i've been enjoying it as I rediscover all the little cool things I like about it and i still think it makes a good first or second language for people.
Having the reinvent the wheel isn't necessarily a bad thing when you're learning. That hacky prototype system I made helped me understand OOP far better than just using classes in other languages had. Even if it didn't really work all that well in the end. It really made me appreciate what a built in class system actually gives you.
One thing I never understood is the mania for OO programming---I regularly see people announce Yet Another OO Module for Lua on the mailing list, and I have to ask myself, "Why?" Is OO the only thing taught these days in school? There are other ways of organizing code than OO.
Now, an object in Lua can have functions that assume a "this" parameter (Lua calls it "self") and thus, it can be viewed as an object qua OO, for example, an open file:
file = io.open("foo.txt","r")
file:setvbuf('no') -- no buffering
file:seek('set',10) -- seek to byte 10 in file
data = file:read(8) -- read 8 bytes
file:close() -- close file
but Lua lacks typical OO features like inheritance, a "class" function or method, which are what the OO modules in Lua always add. It's this mentality, that OO is missing if you don't have inheritance.Even Lua's assumed "self" via the thing:funcname(...) call is just a charade and is secretly just thing.funcname(thing, ...). The split between . and : calling, IME as an informal Lua teacher, is confusing to programming newbies when they first encounter it and I kinda wish the language hadn't chosen _that_ as the thing to spend time implementing.
I try to make a clear distinction between stack and heap stuff and use one or the other where appropriate.
From lua i moved to D for a lot of my heavier projects. I like the way D separates types and uses appropriate reference and copy semantics. Being able to specifically separate heap and stack data and essentially use structs and classes as either copy or reference data just seems fairly straightforward to me.
A struct is just a bunch of stuff of different types grouped up in memory, while a class is essentially a pointer that can be moved to some places in memory and can point to data or functions, use each appropriately and where necessary.
Object-orientation is about grouping together functionality and data. I.e., an object consists of both a struct, and the functions that act on that struct, known as methods.
In OO, your type additionally refers to the functions called on the data, not just on the data. E.g. you might have a car and a boat and they both only have a position and velocity as data, but the boat has a "sink" method the car doesn't.
There are also debates on what qualifies as "true" object orientation. https://stackoverflow.com/questions/250062/what-is-meant-by-...
For games programming in particular, there is a paradigm known as ECS or Entity Component System. (Depending on your view you might call this a sub-paradigm of object orientation, but I think it's much more accurately described as an alternative.) As the Wikipedia article states:
> An entity only consists of an ID and a container of components. The idea is to have no game methods embedded in the entity.
https://en.wikipedia.org/wiki/Entity_component_system
EDIT: There's also the very interesting paradigm that e.g. Julia uses known as "Multiple Dispatch". This is kind of like defining methods on objects, except that the method is defined on a collection of objects instead of a single one.
E.g., in traditional OO, you might have a vehicle#crash method. And it might take another vehicle as argument, e.g. car.crash(truck). But in multiple dispatch you define a function crash that takes in two vehicles, and then depending on the type of the vehicles given, it changes its behaviour so that crash(car, truck) is different from crash(car, car).
In a sense, the function is not thought of as belonging to either the car or the truck, but as belonging to the pair of them, so conceptually this is different to OO.
I'm not particularly familiar with the paradigm so I'm sure I'm not doing it justice, but you can read further on Wikipedia and in the Julia docs, or the given video:
https://en.wikipedia.org/wiki/Multiple_dispatch
https://docs.julialang.org/en/v1/manual/methods/index.html#M...
My pet peeve is that it's somewhat verbose in using keywords rather than single-character punctuation to mark blocks and clauses.