Hacker News new | ask | show | jobs
by grawprog 2200 days ago
Lua's lack of integer support caused me some issues. Using floor() around everything wasn't really an ideal solution and I ended up changing languages for that project.

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.

3 comments

Integer support was added in Lua 5.3 (released in January 2015). It also added binary operators, rendering the bitop module obsolete.

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.

Serious question: How do you organize your data in a semantically meaningful way without something like an object/struct (in a strong type system preferably). I get functional programming and all, but structs just seem like a natural way to organize data.
Structs are a natural way to organize data, but that doesn't necessarily make it "OO". In Lua, a module is typically a table (associative array really) of functions. All of the standard modules that come with Lua are just collections of functions that don't have a concept of "this" (like math or os).

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.
> Lua can have functions that assume a "this" parameter (Lua calls it "self")

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.

The same is true in C++ and Java, only the "self" argument is completely hidden in that case.
To second the use of structs, mostly this. Typically i use structs for most numeric types or anything that doesn't need a method and classes for any reference type with methods. Though, i'll stick to structs/stack allocated data as much as possible.

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 not really about making use of structs - many (most?) functional languages also use structs; it's just a grouping of related data.

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...

https://www.youtube.com/watch?v=kc9HwsxE1OY

You talking about Solarus Engine rang a bell for me as I wondered if it had anything to do with Zelda Solarus, a fan game I played fifteen years ago and what introduced me to RPG Maker. And it does ! It's really heart warming to see people follow through with their own projects for so long, Thanks for the throwback !
Solarus is such an interesting engine in that it's almost certainly more powerful than Defold, but its focus on making a Zelda-like game engine probably makes it harder for users to see how it can be reused for other works.