Lua Functional OOP

Lua Functional Object Oriented Programming is a way you can code that allow you to create classes with ease and simplicity.
It is made to be simple to use and to abide to lua philosophy.

How do you create a functional class

First off you need to create a function. It is functional because it require function to create classes. Inside the function you put an table where it will have the classes method and properties. You can optionally add a metamethod table if you want to add metamethod. You need to return the class table.

local function Human(name, age)
  local class = {
    
  }

  local mt = {
    
  }

  return setmetatable(class, mt)
end

Second of all, you need to set the properties of the class like this:

local function Human(name, age)
  local class = {
    name = name,
    age = age,
    _friends = {}
  }

  local mt = {
    
  }

  return setmetatable(class, mt)
end

If you want to add method you can simply add a function with the self keyword at the first parameter. It’s going to be allowing you to call the class like this joe:isFriendWith(anna).

local function Human(name, age)
  local class = {
    name = name,
    age = age,
    _friends = {},
    isFriendWith = function (self, otherHuman)
      if table.find(self._friends, otherHuman) then
        return true
      else
        return false
      end
    end,
    addFriend = function (self, otherHuman)
      self._friends[#self._friends+1] = otherHuman
      otherHuman:addFriend(self)
    end
  }

  local mt = {
    
  }

  return setnmetatable(class, mt)
end

Functional classes allow you to simply make foreigin properties not allowed like this. It uses the newindex metamethod which is fired when a unknown key is called onto a table.:

local function Human(name, age)
  local class = {
    name = name,
    age = age,
    _friends = {},
    isFriendWith = function (self, otherHuman)
      if table.find(self._friends, otherHuman) then
        return true
      else
        return false
      end
    end,
    addFriend = function (self, otherHuman)
      self._friends[#self._friends+1] = otherHuman
      otherHuman:addFriend(self)
    end
  }

  local mt = {
    __newindex = function (t, k, v)
      error("Cannot set " .. k .. " as its not an valid properties onto the table")
    end
  }

  return setmetatable(class, mt)
end

If you want to inherit an class you can simply do like this:

... 
local AwesomeHuman(name, age)
  local class = Human(name, age)
  rawset(class, "talents", {}) -- use raw set because Human class have __newindex metamethod which prevent adding new keys
  rawset(class, doAwesomeStuff, function (self, what)
    if not table.find(self.talents, what) then
      print(self.name, "cannot do", what, "he is not talent in it.")
    else
      print(self.name, "is doing", what, "with great power")
    end
  end)
end

In conclusion, functional classes are a easy way you can create classes without too much effort and lines of codes.

5 Likes

I don’t know much about functional programming, it doesn’t appeal to me, but is the usual Class.new syntax unfriendly to it?

If so, wouldn’t it be a simple question of returning the function that creates that class anyway?

You’re losing some performance by having functions be created on the construction, wouldn’t this also work, and save memory and speed?

local Class = {}
Class.__index = Class

function Class:__newindex(key)
    error("Cannot set '".. tostring(key).. "' key to Class")
end

function Class:method()
    -- Access members, do whatever you want
end

table.freeze(Class)

local function NewClass()
    return setmetatable({
        _member = {},
        _notYetExistentMember = nil
    }, Class)
end

export type Class = typeof( NewClass() )

return NewClass

Again I don’t understand functional programming much at all, so I just wanna understand this and see if I can mention anything useful or not.

I find it too spammy, it create too much lines.

It also is hard to remember how to do unlike my way of doing classes imo.

Whatever man. The user won’t notice anything. Just look at any python gui app if you want a example to prove that.

Not a bad tutorial, but could use some explaining and minor changes.

Generally, in Roblox, you’ll see classes wrote into modules. This is because it’s the only way to use packages within Luau on Roblox. It’s great for organization and prevents name clashes (as packages always do). The other benefit of modules is private functions and variables, which allows for greater optimization and readability.

For all intents and purposes while creating classes, you should be indexing around your environment(s) rather than writing functions directly into the class (I imagine it would save memory that way, but I could be wrong). In fact, the whole beauty of modules combined with class-based OOP is that you can take serious advantage of Lua metatables for powerful structures. Inheritance is generally what people are aiming for, so why not use __index for it?

This is actually the event behavior of __index, not __newindex. __newindex will become active when you try to update an unknown key, not when you call an unknown key onto a table.

Without taking advantage of these metamethods and all their versatility aren’t you missing out on some of the better organization benefits? That way, you avoid so much rawsetting and rawgetting because inheritance happens the way that it’s supposed to.

The shown behavior creates a metatable for every Human you create, which just isn’t optimal for OOP.

2 Likes

Wouldn’t addFriend result in an infinite loop?

1 Like

yes xd of course it is intended to do that.

/s

1 Like

This is OOP but not functional programming. Functional programming is based off of pure functions which always return the same but this doesnt. Its more or so a simple OOP implementation but in that aspect I find this more messy then the traditional method.

3 Likes

Whatever I don’t really care, it’s how I named it. it is in reality prototype based oop

Hey
good explanation. But lua doesn’t have the concept of class as mentioned, but as I can read from their documentation, it emulates the concept of class.

Anyway, you can use this concept for timer in games for example and to replace redundant scripts in your games using tags.

Maybe in a new version they will implement a full oop concept (c ++).

IIRC Luau has class syntax as one of the things they wanna add.