Skip to content

Dev diary: Researching lua OOP class libraries

Adam Wagner edited this page Jan 17, 2021 · 2 revisions

Helpful reference libs

  TAB = setmetatable({}, { __index = function (self, n)
  self[n] = stringRep('    ', n)
  return self[n]

Minimal Libs

8 Lines: 

https://github.com/sevanspowell/DraygonTensor/blob/develop/project/steps/share/scripts/class.lua 

.. and yet does most of what I want.

  Same project also has a very tiny FSM: https://github.com/sevanspowell/DraygonTensor/blob/develop/project/steps/share/scripts/fsm.lua

    - separate state class: https://github.com/sevanspowell/DraygonTensor/blob/develop/project/steps/share/scripts/state.lua

    ```lua
    function class(members)
      members = members or {}
      local mt = { __index     = members; }
      local function new(_, init)
        return setmetatable(init or {}, mt)
      end
      members.new  = members.new  or new
      return mt
    end
    ```

### Strange Finds

  https://github.com/kwiksher/kwik4tmplt/blob/master/components/store/storeFSM.lua

  This does NOT look clean. But it DOES look *real*. Might be a lesson here.

      Download Manager: https://github.com/kwiksher/kwik4tmplt/blob/master/components/store/downloadManagerV2.lua
      UI: https://github.com/kwiksher/kwik4tmplt/blob/master/components/store/UI.lua
          ↑ this is neat b/c it's a rare example of seeing an FSM in a clearly realistic scenario

Major Libs

#### lash

https://github.com/Taroven/lash

#### loop

https://github.com/ImagicTheCat/Luaoop -- very informative

“Private” instance properties can be achieved using a local table in the class definition with weak keys for the instances.

    ```lua
    local privates = setmetatable({}, {__mode = "k"})

    function Object:__construct()
      privates[self] = { a = 1, b = 2 }
      -- [AW NOTE]: ↑ private props can be stored *outside* the instance, but still be
      -- referenced for as long as the instance is alive. This was a bit of
      -- a light-bulb moment for me, and it could prove quite useful when
      -- redesigning the stackline datastructure in general.
          -- e.g., --> instead of storing references to parents on instances
          -- (which makes copying & inspecting harder), add a class method to
          -- *look up* the parent using instance properties such as `id`, etc.
          -- Note that I *had* planned to address this by 'hiding' this kind
          -- of data in the metatable index table, but this idea might be
          -- even cleaner (avoids needing to even think about dealing with
          -- the side-effects when inheriting - filtering out private data
          -- or somehow earmarking it with a naming convention.. )
    end

    function Object:method()
      local p = privates[self]
      p.a = p.a*p.b
    end
    ```


  #### Base

  https://github.com/okahyphen/base
  Very well-written README. Good refresher on OOP

Happy Accidents

Group-oriented programming

https://github.com/bvssvni/luagroups/blob/master/groups.lua

Group Oriented Programming is a paradigm where computations are done with "groups".

First we need some data to calculate with.

Notice that Clark has no hair member.

`local people = {{name="John", hair=true}, {name="Clark"}}`

We can extract the groups we need on the fly.

```lua
    local name = groups_HasKey(people, "name")
    local hair = groups_HasKey(people, "hair")

    local name_and_hair = name * hair
  ```

Loop through each index in group, starting at offset 1 to match Lua index.
```lua
    local person
    for i in group(name_and_hair, 1) do
        person = people[i]
        print(person.name)
    end
```

A group generator is a function that iterates through an array and creates a group. The easiest way of doing this is by using the 'ByFunction' function, like this:


```lua
  function groups_LessThan(data, prop, value, region)
      return groups_ByFunction(data, function (data, i)
          local item = data[i]
          if item[prop] < value then return true
          else return false end
      end, region)
  end
```

A group generator can also take a region group as argument to limit the scope of iterations. Using a region group is faster.

```lua
    -- A bit slower.
    local US = groups_HasKey(people, "US")
    local name = groups_HasKey(people, "name")
    local name_and_in_US = US * name

    -- A bit faster.
    local US = groups_HasKey(people, "US")
    local name_and_in_US = groups_HasKey(people, "name", US)
```

It is the group generator that makes the difference. The performance of the algebra is not depending on the size of data, but how fragmented the information in the group is. This is completely determined by the data. When it comes to speed, it is the generators that matters.

OOP Toolbox

AMAZING! Super well-commented metatable utils & good examples of how metatamethods can be deployed to achieve specific OOP effects
  https://github.com/bhou/Bo-LuaOOP/tree/master/bhou/oo

Pretty good. Found string indexing via brackets trick here:
  https://github.com/Paradigm-MP/oof/blob/master/shared/lua-additions/lua-additions.lua

Also has well-commented base class file:
  https://github.com/Paradigm-MP/oof/blob/master/shared/object-oriented/class.lua

And getter-setter mixins:
  https://github.com/Paradigm-MP/oof/blob/master/shared/object-oriented/shGetterSetter.lua

OOPlib, ClassLib, and Async: https://github.com/sbx320/lua_utils

One-off dude's Class libs: https://github.com/jonstoler/class.lua