Need help stacking or chaining functions together - lua

Im wondering how i can get something like this to work:
Test ={}
function Test:returnNumber5 ()
return 5
end
function Test:add5( num )
return num + 5
end
function randumFunction()
local num = Test:returnNumber5():add5()
if num == 10 then
print(num)
end
end
Im looking to stack or chain together code:
Test:returnNumber5():add5():add5():add5()
I dont understand how to setup long chains of functions. I understand how to call them and get them to do what i want when modding other games but dont know why its not working for my game. I put the test code above into my game and it just crashes my game with no details
Using Love2D framework
Please help if u can
Thanks!

First of all, you need constructor to object creation:
Test = {}
function Test:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
Second thing is to return self if you want use form object:doSomething():doSomethingElse().
Test = {}
function Test:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function Test:setNumber5()
self.num = 5
return self
end
function Test:add5()
self.num = self.num + 5
return self
end
function Test:value()
return self.num
end
function randumFunction()
local num = Test:new():setNumber5():add5():value()
if num == 10 then
print(num)
end
end

Related

How to inherit method?

I want to inherit method "GetName" or other methods from "Create" for "CreateInherited" and i want save unique methods from "CreateInherited" (like "GetInheritName"), but i dont know how.
My test code:
local MainTbl = {}
function MainTbl:Create(name)
local tbl = {}
tbl.name = name or 'Null'
function tbl:GetName()
return self.name
end
setmetatable(tbl, self)
self.__index = self
return tbl
end
function MainTbl:CreateInherited(name)
local tbl = {}
tbl.name = name or 'Null'
function tbl:GetInheritName()
return self.name
end
setmetatable(tbl, self)
self.__index = self
return tbl
end
local Man = MainTbl:Create('Man')
local Woman = MainTbl:CreateInherited('Woman')
print(Man:GetName())
print(Woman:GetName())
print(Woman:GetInheritName())
If I understand you, you're trying to put two different constructors into a single class. Notice that Create does most of the work that CreateInherited needs to do, so you can save yourself a lot of repeated code by calling Create inside CreateInherited. Instead of starting with an empty table, you can start with a fully formed instance from Create and add a method to it.
function MainTbl:CreateInherited(name)
local tbl = self:Create(name)
function tbl:GetInheritName()
return self.name
end
return tbl
end

I'm getting the error "attempt to index local self (a number value)

require 'class'
Paddle=class{}
function Paddle:init(x,y,width,height)
self.x=x
self.y=y
self.width=width
self.height=height
self.dy=0
end function Paddle:update(dt)
if self.dy < 0 then
self.y = math.max(`enter code here`0, self.y + self.dy * dt)
else
self.y=math.min(VIRTUAL_HEIGHT,-self.height,self.y+self.dy*dt)
end
end
function Paddle:render()
love.graphics.rectangle('fill',self.x,self.y,self.width,self.height)
end
I am following the course CS50 lecture 0 pong update 5, and the same code is working for the teacher. I don't know why this is happening neither understand the problem because it makes no sense. If you want, here's 'class'. This problem isn't happening in the other class I made called 'ball' which does exactly the same thing. I also defined self.dy, and it does have a value "0" so I don't know why it does that error and what that error means.
local function include_helper(to, from, seen)
if from == nil then
return to
elseif type(from) ~= 'table' then
return from
elseif seen[from] then
return seen[from]
end
seen[from] = to
for k,v in pairs(from) do
k = include_helper({}, k, seen) -- keys might also be tables
if to[k] == nil then
to[k] = include_helper({}, v, seen)
end
end
return to
end
-- deeply copies `other' into `class'. keys in `other' that are already
-- defined in `class' are omitted
local function include(class, other)
return include_helper(class, other, {})
end
-- returns a deep copy of `other'
local function clone(other)
return setmetatable(include({}, other), getmetatable(other))
end
local function new(class)
-- mixins
class = class or {} -- class can be nil
local inc = class.__includes or {}
if getmetatable(inc) then inc = {inc} end
for _, other in ipairs(inc) do
if type(other) == "string" then
other = _G[other]
end
include(class, other)
end
-- class implementation
class.__index = class
class.init = class.init or class[1] or function() end
class.include = class.include or include
class.clone = class.clone or clone
-- constructor call
return setmetatable(class, {__call = function(c, ...)
local o = setmetatable({}, c)
o:init(...)
return o
end})
end
-- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons).
if class_commons ~= false and not common then
common = {}
function common.class(name, prototype, parent)
return new{__includes = {prototype, parent}}
end
function common.instance(class, ...)
return class(...)
end
end
-- the module
return setmetatable({new = new, include = include, clone = clone},
{__call = function(_,...) return new(...) end})
So this is the part where I call the update function, which is what someone said might be the error
function love.update(dt)
if love.keyboard.isDown('w') then
player1.dy=-PADDLE_SPEED
elseif love.keyboard.isDown('s') then
player1.dy=PADDLE_SPEED
else
player1.dy=0
end
if love.keyboard.isDown('up') then
player2.dy=-PADDLE_SPEED
elseif love.keyboard.isDown('down') then
player2.dy=PADDLE_SPEED
else
player2.dy=0
end
if gameState=='play' then
ball.update(dt)
end
player1.update(dt)
player2.update(dt)
This error is pretty clear on what you're doing wrong.
You're indexing local self, a number value.
That means that somewhere you're doing something like self.dy where self is not a table but a number and using the index operator . on numbers is not allowed as it does not make any sense.
The question is why self is not a table.
function myTable:myFunction() end
is short (syntactic sugar) for
function myTable.myFunction(self) end
and the function call
myTable:myFunction() is short for myTable.myFunction(myTable)
Please refer to the Lua manual.
Function Calls
Function Definitions
Find a function in your code that is defined with : and called with . and gets a number as first argument during that call.
That way a number ends up where you expect self.
I guess the error is in the main.lua which you did not provide.
There you have several calls to Paddle:update(dt). Writing myPaddle.update(dt) would cause that error for example. But I can't tell for sure as you did not provide your code.
But that it works for the teacher, but not for you is usually because you do something different/wrong.
Edit:
As you've provided more code I can tell for sure that the observed error is caused by
ball.update(dt)
player1.update(dt)
player2.update(dt)
This will put dt a number value, where the function expects self, the table ball.
replace it by
ball.update(ball, dt) or ball:update(dt)
player1.update(player1, dt) or player1:update(dt)
player2.update(player2, dt) or player2:update(dt)

Lua inserting a record to a table is failing

I have a main script as follows . This script is called script.lua (for the sake of this example)
require "modules\\myparentclass"
require "modules\\condition"
require "modules\\helpers"
require "constants"
parentclass = MyParentClass:new()
print ("MyParentClass Type : " .. parentclass:getCode())
-- add conditions
-- condition 1
condition1 = Condition:new(nil,"Are you happy?" , "YES")
parentclass:addCondition(condition1)
-- -- condition 2
condition2 = Condition:new(nil,"Are you sad?" , "NO")
parentclass:addCondition(condition2)
local l = parentclass:getConditions()
print(l[2]:getQuestion())
I have another class called MyParentClass whose code is as follows
require "constants"
require "modules\\condition"
require "modules\\helpers"
-- Meta class
MyParentClass = {code = ""}
function MyParentClass:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
self.condition = condition
self.conditions = {}
return o
end
function MyParentClass:getCode ()
return "Parent Class"
end
function MyParentClass:addCondition(condition)
print(condition)
table.insert(self.conditions,condition)
print('record inserted')
-- self.conditions = {next= self.conditions, value = condition}
end
function MyParentClass:getConditions()
return self.conditions
end
and I have a third class , Conditions which is as follows
require "constants"
-- Meta class
Condition = {question="", answer=""}
function Condition:new (o, question,answer)
o = o or {}
setmetatable(o, self)
self.__index = self
self.question = question or nil
self.answer = answer or nil
return o
end
function Condition:getCode ()
return CONDITION_TYPE
end
function Condition:getQuestion()
return self.question
end
function Condition:getAnswer()
return self.answer
end
The idea is that in the main script (script.lua) ,
I can create a new parent class.
Each parent class can have multiple conditions (aka questions).
For me, the first part is working. However I am failing with the second part. Whenever I run the script , I get two instances of the second question. Please see the below snapshot for more details.
.
Ideally, I would like to have both the conditions displayed ("are you happy?" and "are you sad?") but that is currently not the case.
Can you please help me out with this one?
Take a look at your constructor
function Condition:new (o, question,answer)
o = o or {}
setmetatable(o, self)
self.__index = self
self.question = question or nil
self.answer = answer or nil
return o
end
Everytime you call this you change the value of Condition.question and Condition.answer as self refers to Condition, not to your new object o!
So what you actually do is create 2 new tables condition1 and condition2 which both don't have their own .answer and .question. Therefor you access their metatable Condition which after you created condition2 contains: "Are you sad?" , "NO")
If you want to initialize members in your constructor you have to use o.answer and o.question.
Make sure you understand how that metatable stuff actually works.

infinite recursion in __index metamethod

As I understand lua don't call __index unless the key wasn't found in the table so I have that code and it suffers from infinite recursion in the __index part which I don't get as both values used inside the __index function already exist in the table!?
This is basically a test script for trying to save the size of the table in a memory to retreive when # is called
do
local lenKey,originalKey = {},{}
fastKey = {}
fastKey.__len = function(t) return t[lenKey] end
fastKey.__index = function (t,k)
t[lenKey] = t[lenKey] +1
return t[oroginalKey][k]
end
fastKey.__newindex = function(t,k,v) t[originalKey][k] = v end
fastKey.__pairs = function ()
return function (t, k)
return next(t[oroginalKey], k)
end
end
function fastLen(t)
local proxy = {}
local c = 0
for _ in pairs(t) do
c=c+1
end
proxy[lenKey] = c
proxy[originalKey] = t
setmetatable(proxy,fastKey)
return proxy
end
end
n = fastLen{1,2,3,x=5}
--n:insert(1) -- here the __index is called and gets stackoverflow
print(#n)
You've got two typos in there: both the __index and __pairs functions contain oroginalKey instead of originalKey.

lua - calling a function from a string

From what I've read on this site the below should work.
Can some kindly soul please point out where I'm going wrong?
I've embedded more description and print returns in the code hopefully to make easier reading
local m = {
{opt = "Solar Panels", cmd = "solarPanel"}
-- There are many more options here.
}
function doTheMenu()
print("Welcome to Spyder's Factory")
print("")
print("What would you like to make?")
local n = 1
local l = #m - 1
while true do --This while loop may or may not be relevant to the question, it's the menu
term.clear() --this is ComputerCraft lua, the term function is defined
term.setCursorPos(1,2) --elsewhere in an API
for i, j in pairs(m) do
if i == n then
if i < 10 then print(i, " ["..j.opt.."]") else print(i, " ["..j.opt.."]") end
fsel = j.cmd --set fsel to the function name I require in case of a break
tsel = j.opt --Ditto, tsel, human-friendly name
else
if i < 10 then print(i, " "..j.opt) else print(i, " "..j.opt) end
end
end
local a, b = os.pullEvent("key")
if b == 200 and n > 1 then n = n - 1 end
if b == 208 and n <= l then n = n + 1 end
if b == 28 then break end
end
write("\nSure, how many "..tsel.."? ")
qty = tonumber(read())
req[fsel] = req[fsel] + qty
str = fsel.."("..qty..")"
print("Loading function '"..fsel.."("..qty..")'") --Returns "Loading function 'solarPanel(1)'"
func = loadstring(str)
print(func) --Returns "function: 2cdfc5a7"
print("Loading function")
func() --The error line, Returns "string:1: attempt to call nil"
--tellUserWhatNeed()
--makeItHappen()
end
doTheMenu()
The issue is the code fails to run with the error:
string:1 attempt to call nil
Also what is term variable, if that's all your code, term is not defined and is null)
That said: either _G[fsel] is nil or fsel is nil ?
Are you sure you have function declared in _G with the name stored in fsel?
e.i. call before the problem line print (_G[fsel]) to see what it gives you.
This was the solution that ended up working:
local f = loadstring(str)
if f then
setfenv(f, getfenv())
f()
end
This replaces the lines above:
print("Loading function '"..fsel.."("..qty..")'")
func = loadstring(str)
print(func)
print("Loading function")
func()
As well as adding basic error handling for loading the function

Resources