The programming paradigm of lua

As my father is a “software engineer” and my mother is a Biophysical chemist, I have been raised In a household with mathematics and Comp-sci. When I was about 6 or 7 years old, I "learned " (or as my father likes to say: “hacked around in”) my first programming language: basic4GL (a combination of basic and OpenGL.) Since then I have mastered several programming languages including java, OpenGL (if that counts), and C/C++. As a 16 year old, I hope to master other languages to support my true love, mathematics. Having programmed in c++ and java, I generally attempt to immediately apply object oriented programming methods (I.e. utilizing “objects” defied in classes to develop the application) in any programming language -I event tried to apply OO (object oriented) programming to lisp… Didn’t work :frowning: - anyway, when I learned lua dabbling around inside of Codea (BTW really nice job making codea, it is REALLY easy to pick up lua and the codea API inside of this IDE) I again attempted to apply OO methods to lua, and struggled and semi-succeeded. I was curious about what paradigm lua fell best into (functional, procedural, scripting, OO, etc…) and what method I should attempt to utilize when programming in lua/Codea.
Thanks!

I tend to treat Lua in a straight forward OO approach. That said, I’m not above treating scope a lot more cavalierly than I would in Objective-C (i.e. referencing other objects from within an object method) and don’t make much of a pretense of defining getters and setters. So in some sense, I treat Lua as “OO Lite,” somewhat in the same vein as VB 6, but with better handling of inheritance.

The nice thing about Lua is that it supports a lot of programming styles. The bad thing about Lua is… it supports a lot of programming styles. That is, you can tackle a problem using almost any approach you’d like, but if you want the languange to provide some of the rigidity that both constrains, and informs, other languages, it’ll take extra work.

Lua is sort of object-oriented. Technically, it’s not: true object-oriented languages support several things: encapsulation, access control, inheritance, polymorphism, and a few other buzzwords that make CS nerds excited.

However, Lua can simulate object-oriented behavior well enough for most uses.

tl;dr explanation: use class() to declare a class. simply add new methods to an instance to subclass, like this:

parent=class()
parent.foo="hello"
parent.methodA()
end

child = class(parent)
child.bar="there"
child.methodB()
end

objectParent=parent()
objectChild=child()

longer explanation:

Non-atomic variables in Lua are either userdata (a special case) or tables.

A table is also known as a Dictionary in MS languages like Visual Basic and c#. You can set and access values on a table using dot notation (foo.x) or index notation (foo[x], foo[“abc”]), and the index can be any type, Integers and strings being the most efficient indexers. Integer indices will result in a sorted list, and string indices appear to be indexed as a hash table.

However, we don’t get true polymorphism quite yet. Polymorphism requires methods to be distinct for each class in the inheritance hierarchy, yet data to be the same.

So while parent:foo() and child:foo() can have different behaviors, child.x and parent.x must always have the same value.

There’s a hidden part called a metatable. Short explanation is that metatables allow you to change an object’s internal behavior. Codea implements all these changes for us in the class() function, so we just need to declare our class objects by assigning them to the result of class(), like this:

ParentClass = class()

So by creating a class object with the class() function, then creating child classes from the your parent object with child = parent(), you can basically act as if Lua objects are classes just like in c++ or Java.

Finally, there’s the “self” keyword. Self is a special keyword that means “this object” when used in any object method. This is actually implicitly passed in to a method when you use the : syntax, so these two calls are functionally identical:

foo:print()
foo.print(foo)

So if you want to address the behavior of a parent class, the easy way to do so is something like:

parentclass.method(childObject, argument1, argument2, ...)

Note the dot, rather than the colon. That tells Lua that we’re going to pass in our own “self” object, and so we can pass in any “self” we want, including one from a different class.

I think that about covers the basics… hopefully I didn’t mess up my explanation too badly.

Thanks TomXP411 and Mark. So one can “simulate” OO programming in lua by utilizing metatables which functionally extend the standard table. Thanks for clearing up several of my misconceptions.

No problem.

It’s also worth noting that since Lua basically doesn’t type check, it makes your life both easier and more complicated at the same time.

There’s no need to declare Interfaces, since there’s nothing of the sort in Lua, but if you’re relying on data that you don’t control 100%, you’ll need to be more careful about type checking. For example, you might include a check to see if a particular method or variable exists (check out the table functions) before using it.

In other words, since you don’t get the wonderful type safety languages like c++, you will have to be much more careful to assert that function parameters actually contain the kind of data you’re looking for.

On the bright side, it also means that you don’t need to create an Interface just to be able to implement a common function in all of your classes: you can just add the function to the classes that need it.

From a RAD standpoint, it makes Lua a lot of fun. From a professional development standpoint, it makes Lua scary. Either way, it has its uses.

@tompxp411 very interesting.
If sby wanted to, couldnt he emulate the strict interface c++ check of a class via the metatable? So creating a classStrict() function to use instead of class()? (Naive question, i dont know the answer).

@tomxp411

One minor correction. When you do sth = parent() then you are declaring sth to be an instance of parent. If you want to declare a child class then you do child = class(parent).

thanks. I had forgotten that. I’ll have to go update my example.

@Jmv38 yes, you can always check the class name of an object at runtime. However, type safety in strongly typed languages means you can’t even compile the code if you tried to pass in the wrong parameter type.

This is the chief weakness in languages without strong typing: since the compiler can’t enforce type safety, you can make a lot of dumb coding mistakes more easily than in a stricter language.

That doesn’t mean you can’t write bad code in c… or good code in Lua. In the end, code is only as good as the coder. Unfortunately, the programming world has a lot of egos, including far too many that don’t reflect reality.