"attempt to call table" without for - oop

When I call the method stream that I made, with any table as argument, I get the error "attempt to call table".
As far as I know this error only occurs when I use a for wrong, but I don't have a for in the code that is executed...
function stream(input)
...
local function _stream(input)
local result = {
_stream = true,
_data = input._data or input,
-- Without the Operation-wrapping no function could access the input
-- Intermediate Operations
concat = function(str) return _concat(input,str) end,
distinct = function(func) return _distinct(input,func) end,
filter = function(func) return _filter(input,func) end,
limit = function(n) return _limit(input,n) end,
map = function(func) return _map(input,func) end,
skip = function(n) return _skip(input,n) end,
sort = function(func) return _sort(input,func) end,
split = function(func) return _split(input,func) end,
-- Terminal Operations
allmatch = function(func) return _allmatch(input,func) end,
anymatch = function(func) return _anymatch(input,func) end,
collect = function(coll) return _collect(input,coll) end,
count = function() return _count(input) end,
foreach = function(func) return _foreach(input,func) end,
max = function(func) return _max(input,func) end,
min = function(func) return _min(input,func) end,
nonematch = function(func) return _nonematch(input,func) end,
reduce = function(init,op) return _reduce(input,init,op) end,
toArray = function() return _toArray(input) end
}
return result
end
if input == nil then
error("input must be of type table, but was nil")
elseif type(input) ~= "table" then
error("input must be of type table, but was a "..type(input)..": "..input)
end
return _stream(input)
end
table.stream = stream
Full Source - Older Version (where the argument gets deleted for some reason)
I want to use the method for a more stream-based programming style.
Very similar to this project, but more not only for numbers and with named keys.

In your code
function stream(input)
-- ...
local function _count()
local count = 0
for k, v in pairs(input._data) do
count = count + 1
end
return count
end
-- ...
local function _stream(input)
local result = {
_stream = true,
_data = input._data or input,
-- ...
count = _count,
-- ...
}
return result
end
return _stream(input)
end
print(stream({1,2,3}).count())
the created object _stream(input) does contain _data field, but input upvalue still refers to your argument {1,2,3} which doesn't have _data field.
It could be fixed by working with the object instead of input argument:
function stream(input)
-- ...
local obj
local function _count()
local count = 0
for k, v in pairs(obj._data) do
count = count + 1
end
return count
end
-- ...
local function _stream(input)
local result = {
_stream = true,
_data = input._data or input,
-- ...
count = _count,
-- ...
}
return result
end
obj = _stream(input)
return obj
end
print(stream({1,2,3}).count())

Related

Lua oop static object value

How would I make self.character.data().bank the same to all instances of the class
even when using the function setBank? currently when using setBank it only updates self.character.data().bank on the one instance if it makes sense
_G.GetUser = {
users = {},
users_group = {},
userData = {},
CurrentCharacter = {}
}
_G.GetUserMethods = {}
GetUserMethods.__call = function(self, source)
local o = setmetatable({}, {
__index = self
})
o.src = source
o.id = self.users[o.src]
o.rank = self.users_group[o.src]
return o
end
GetUserMethods.__index = {
getCurrentCharacter = function(self)
self.character = {}
self.character.id = self.CurrentCharacter[self.id]
self.character.data = function()
return self.userData[self.character.id]
end
self.character.setBank = function(v)
if self.character.data() then
self.character.data().bank = v
end
end
self.character.getBank = function()
if self.character.data() then
return self.character.data().bank
end
return nil
end
return self.character
end
}
setmetatable(GetUser, GetUserMethods)
Replace
importClass {'getuser'}
with
if not _G.GetUser then
importClass {'getuser'}
end
in each file.

Select count(col_name) in sqlite (Swift) not working

I am using the sqlite wrapper here to access my sqlite database in Swift.
I wrote this code based on the wrapper to count the items on a table.
public func numberOfRows() -> Int {
let cmd = """
SELECT count(*) from \(self.tableName)
"""
do{
let db = DatabaseUtils.getInstance().getConnection()
let stmt = try db.prepare( cmd )
if try stmt.step() == .row {
return Int(from: stmt,index: 1) ?? -1
}
return -1
}catch {
Log.out("Error occurred while fetching count data in \(tableName)")
return -1
}
}
But it keeps returning -1 as the logic instructs when the count is not found.
Every other thing works so far; create tables, inserts, batched inserts.
Also a select count(col_name) from table_name where some_col = "?" also works.
QUESTION:
How do I remedy it to work for
SELECT count(*) from table_name?
The column numbers when returning values (e.g. the result of sqlite3_column_xxx) are zero-based. You’re attempting to retrieve column 1, when you meant column 0.
By the way, if you want to detect invalid index, you can remove that nil coalescing operator. E.g., so, instead of:
if try stmt.step() == .row {
return Int(from: stmt,index: 1) ?? -1
}
You could instead check to see if not only if step succeeded, but also that Int(from:index:) returned a non-nil value:
if try stmt.step() == .row {
if let count = Int(from: stmt, index: 1) {
return count
} else {
// do whatever you want when it fails, e.g.
fatalError("no value returned; invalid column index?")
}
}
Or perhaps more succinctly:
if try stmt.step() == .row, let count = Int(from: stmt, index: 1) {
return count
} else {
fatalError("no value returned; invalid column index?")
}
That would lead you to recognize that you need the 0-based index:
if try stmt.step() == .row, let count = Int(from: stmt, index: 0) {
return count
} else {
fatalError("no value returned; invalid column index?")
}

Whole Structure is being replaced with the last pointer Value

In my program I have used an array of pointers as a structure variable to get first name and second name from the user.
The following is my function call statement:
ret_val = update_person(&ptr_person[person_index],f_name,s_name);
where ptr_person[SIZE] is a pointer variable and f_name and s_name are character array variables.
The following is my function definition where name_ret is int:
name_ret update_person(person_name_et **person,char *first_arg,char *second_arg)
{
int val = SUCCESS, val1 = SUCCESS,val2= SUCCESS;
int f_len = sizeof(first_arg);
int s_len = sizeof(second_arg);
val2 = remove_newline(first_arg);
val1 = remove_newline(second_arg);
val = allocate_person(person, f_len, s_len);
if((val && val1) == SUCCESS)
{
(*person)->first_name = first_arg;
(*person)->second_name = second_arg;
return SUCCESS;
}
else
{
return FAILURE;
}
}
The problem in the code is it works fine at the instance but when the function is called next iteration the ptr_Person[0] is replaced with ptr_person[1] and if we have 5 instances then all the 5 variables are replaced by the last values.

Lua script throws error "attempt to call a nil value (field 'deposit')"

I have this Lua script, which is supposed to create a new class, create an instance and call functions, but there's an error in which I actually call the methods.
Account = {
balance = 0,
new = function(self,o)
o = o or {}
setmetatable(o,self)
self.__index = self
return o
end,
deposit = function(self,money)
self.balance = self.balance + money
end,
withdraw = function(self,money)
self.balance = self.balance - money
end
}
new_account = Account.new()
print(new_account.balance)
new_account.deposit(23)
new_account.deposit(1)
print(new_account.balance)
It keeps throwing this error:
attempt to call a nil value (field 'deposit')
It seems to work like this:
Account = {
balance = 0,
}
function Account:new(o)
o = o or {}
setmetatable(o,self)
self.__index = self
return o
end
function Account:deposit(money)
self.balance = self.balance + money
end
function Account:withdraw(money)
self.balance = self.balance - money
end
function Account:get_balance()
return self.balance
end
acc = Account:new({})
print(acc.balance)
acc:deposit(1920)
print(acc:get_balance())
I don't seem to get what's wrong. Maybe it's the ':' operator that only works?
Yes, you need to use : to call methods:
new_account = Account:new()
print(new_account.balance)
new_account:deposit(23)
new_account:deposit(1)
print(new_account.balance)
Account:new() is sugar for Account.new(Account), etc.

Lua inheritance

I have two classes in Lua.
test1 = {test1Data = 123, id= {0,3}}
function test1:hello()
print 'HELLO!'
end
function test1:new (inp)
inp = inp or {}
setmetatable(inp, self)
self.__index = self
return inp
end
test2 = {}
function test2:bye ()
print 'BYE!'
end
function test2:create_inst( baseClass )
local new_class = {}
local class_mt = { __index = new_class }
function new_class:create()
local newinst = {}
setmetatable( newinst, class_mt )
return newinst
end
if baseClass then
setmetatable( new_class, { __index = baseClass } )
end
return new_class
end
a = test1:new({passData='abc'})
print (a.test1Data, a.passData, a:hello())
c = test2:create_inst(a)
print (c.test1Data, c.passData,c:hello(), c:bye())
I want to inherit test2 from test but leave in the specified test2 methods bye.
Everything works except for bye:method.
How can I solve this problem?
You return an empty table in test2:create_inst(), at no point does anything reference test2, so the function test2:bye() is not in the table returned by test2:create_inst()
In your code, test2 actually has nothing to do with the table you are instancing, this new_class table you return from test2:create_inst is the new instance. So naturally it has no field named bye. Simple modification:
function test2:create_inst( baseClass )
...
if baseClass then
setmetatable( new_class, { __index = baseClass } )
end
...
function new_class:bye()
print("bye!")
end
return new_class
end
I think the answer want to implement Multi-Inheritance that new_class inherit "test2" and "baseClass".
local function search(k, objlist)
local i = 0
local v
while objlist[i] then
v = objlist[i][k]
if v then return v end
end
end
function class(...)
local parents = (...)
local object = {}
function object:new(o)
o = o or {}
setmetatable(o, object)
return o
end
object.__index = object
setmetatable(object,
{__index=function(t, k)
search(k, parents)
end})
return object
end
c = class(a, test2)
print(c.test1Data, c.passData,c:hello(), c:bye())