calling a function with a table constructor? - lua

i was learning on how to create and use a class on a youtube video and i came across this code
cc = {calo = 0, goal = 1500}
function cc:new(t)
t = t or {}
setmetatable(t,self)
self.__index = self
return t
end
a = cc:new{goal = 100}
i dont understand this part a = cc:new{goal = 100} this is the first time where i see a function being called with anything other then (). i have 2 guesses on what this does maybe it replaces the parameter of cc:new function with {goal = 100} or maybe the function is called and t table is assigned to the variable then assigning the table with {goal = 100}? pls correct me if im wrong

first, {goal = 100} is just an argument.
second, cc:new{goal = 100} is equal to cc:new({goal = 100})
this is a syntactic sugar, you can call a function without brackets if theres only one argument and its type is string or table literal
example:
function foo(x)
print(x)
return foo
end
foo "Hello" "World"
this will output "Hello" and "World"
if you want to call a function without brackets and using multiple arguments, the function you gonna call must return another function for the next argument.
the another function is not always the original one
it may be recursive

Related

For/while loop with an f-string

How do I correctly perform a for-loop that returns as a f-string (like in Python.)
For example,
for i=10, 1, -1 do
test = string.gsub('checkbox[val = "a"]','a', i)
return test
end
Returns
checkbox[v10l = "10"]
However, I was expecting:
checkbox[val = "1"]
checkbox[val = "2"]
..
..
checkbox[val = "10"]
I'm honestly not sure what are you trying to do here. Lua has no supports for f-strings and you're trying to return multiple times from function?
This is probably the closest to what you want:
for i=1, 10 do
print(string.format('checkbox[val = "%d"]', i))
end
You're doing the following:
Running for loop from 10 to 1, in opposite direction of what you want.
Replacing all occurrences of string a in checkbox[val = "a"] with loop variable, giving you resulting string and assigning that to (global, which is not good) variable test.
Returning string you just got, thus exiting loop and function that contains loop.
If you're trying to pass multiple values from loop to the outside world, you can do one of the following:
Add them into table and return it:
local tab = {}
for i=1, 10 do
tab[i] = string.format('checkbox[val = "%d"]', i)
end
return tab
Accept callback, so caller passes in a function to call on each value:
function example(cb)
for i=1, 10 do
cb(string.format('checkbox[val = "%d"]', i))
end
end
example(print) -- Here, we pass `print` as a callback, but it's usually your own function
Choose whatever better suits your particular interface.

Lua: Workaround for boolean conversion of a class variable when enclosed in parentheses

In the below code, can anyone explain why does t1:print() works but (t1):print fails. I am attempting to make something like (t1 * 3):print() work without using an intermediate variable.
function classTestTable(members)
members = members or {}
local mt = {
__metatable = members;
__index = members;
}
function mt.print(self)
print("something")
end
return mt
end
TestTable = {}
TestTable_mt = ClassTestTable(TestTable)
function TestTable:new()
return setmetatable({targ1 = 1}, TestTable_mt )
end
TestTable t1 = TestTable:new()
t1:print() -- works fine.
(t1):print() -- fails with error "attempt to call a boolean value"
Lua expressions can extend over multiple lines.
print
(3)
Will print 3
So
t1:print()
(t1):print()
actually is equivalent to
t1:print()(t1):print()
or
local a = t1:print()
local b = a(t1)
b:print()
So you're calling the return value of t1:print()
To avoid that follow Egors advice and separate both statements with a semicolon.
t1:print();(t1):print()

Passing value as a parameter in Lua

A = {}
function A:text()
return 100
end
print(A["text"]()) -- prints "100"
----------------------------------
A = {}
function A:text(value)
return value
end
print(A["text"](100)) -- prints "nil"
Is there a way that I can pass a value as a parameter and return the same value?I need to loop through 5 functions...
You could, if you declared your function correctly.
function A:text(value)
This creates a function that takes two parameters. The : is what's responsible for that. The first parameter is an implicitly declared parameter called self. The second is value. This function is intended to be called as A:text(100) or with A["text"](A, 100).
These are for class-member-like functions.
You should instead create the function like this:
function A.text(value)
This creates a function that takes one parameter.
As "Nicol Bolas" pointed out, I add table/self parameter and it worked fine.
-- from "A["text"](100)" to "A["text"](self, 100)" or "A["text"](A, 100)"
A = {}
B = {"text", "type"}
function A:text(value)
return "text "..value
end
function A:type(value)
return "type "..value
end
for i=1, 3 do
for j=1, #B do
print(A[B[j]](self, i)) -- prints "text 1 type 1 text 2 type 2 text 3 type 3"
end
end

is there aliasing in lua similar to ruby

Can you alias a function (not in a class) in LUA in a similar way to Ruby? In ruby you would do something like this:
alias new_name_for_method method()
def method()
new_name_for_method() # Call original method then do custom code
i = 12 # New code
end
I'm asking because I'm developing for a program that uses LUA scripting and I need to override a function that is declared in a default file.
In Lua, functions are values, treated like any other value (number, string, table, etc.) You can refer to a function value via as many variables as you like.
In your case:
local oldmethod = method
function method(...)
oldmethod(...)
i = 12 -- new code
end
keep in mind that
function method() end
is shorthand for:
method = function() end
function() end just creates a function value, which we assign to the variable method. We could turn around and store that same value in a dozen other variables, or assign a string or number to the method variable. In Lua, variables do not have type, only values do.
More illustration:
print("Hello, World")
donut = print
donut("Hello, World")
t = { foo = { bar = donut } }
t.foo.bar("Hello, World")
assert(t.foo.bar == print) -- same value
FYI, when wrapping a function, if you want its old behavior to be unaffected for now and forever, even if its signature changes, you need to be forward all arguments and return values.
For a pre-hook (new code invoked before the old), this is trivial:
local oldmethod = method
function method(...)
i = 12 -- new code
return oldmethod(...)
end
A post-hook (new code invoked after the old) is a bit more expensive; Lua supports multiple return values and we have to store them all, which requires creating a table:
local oldmethod = method
function method(...)
local return_values = { oldmethod(...) }
i = 12 -- new code
return unpack(return_values)
end
In lua, you can simply override a variable by creating a new function or variable with the same name.
function name_to_override()
print('hi')
end
If you still want to be able to call the old function:
local old_function = name_to_override
function name_to_override()
old_function()
print('hi')
end

Lua - Can a function be called from a table value and its value returned

I'm asking for help regarding this matter as I cannot quite get the grasp of if it is possible let alone if I am just doing it wrong.
my = {
Question = AskQuestion()
}
function AskQuestion()
return "What do you want to know?"
end
My intention is to do, print(my.Question) and have it return "What do you want to know?", So far I have just ran into headaches and errors trying to get this to work.
Further on should this be solved I can presume rather than figuring it out myself I may as well ask in addition. What about passing on a value to the function.
my = {
Answer = MyAnswer(vAnswer)
}
function MyAnswer(vAnswer)
if vAnswer == "42" then return "Life.." end
end
So here I would want to do, print(my.Answer(42)) and it return "Life.."
Just invert your declaration:
function AskQuestion()
return "What do you want to know?"
end
my = {
Question = AskQuestion()
}
Since Lua is interpreted you have to have everything defined before you can use.
When setting a variable you don't need to pass the (vAnswer) because it is not a defition, it is just a existing-function usage, so change to:
function MyAnswer(vAnswer)
if vAnswer == "42" then return "Life.." end
end
my = {
Answer = MyAnswer
}
I am assuming here that you are using a different my table, but you should get the picture.
A function is a first class entity in Lua so you can set a variable or table field to be a function:
function f() end -- do nothing
a = f
Then a refers to f, you can do to/with a as you can with f, such as calling it:
a() -- calls f()
Then you can set a to be another function, and call it:
function g(x) end
a = g -- a is now function g
a(1) -- calls g(1)
Everything in the above examples can be done with table fields too:
tt = {
f = function() print('hi') end,
g = function(x) print(x) end
}
tt.f() -- calls tt.f function
a = tt.f
a() -- calls tt.f
tt.h = a
tt.h() -- calls tt.f
tt.f = print -- now tt.f is print function
tt.f('bye') -- prints 'bye'

Resources