This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
corisco1917's profile picture

[SOLVED][LUA] calling methods as strings

Started by corisco1917, 07 February 2013 - 07:25 AM
corisco1917 #1
Posted 07 February 2013 - 08:25 AM
so i have this little API i'm working on to store usefull information on a "server computer"

so far i've written this as my API
Spoiler

if fs.exists("disk/db") then
print("db api loaded")
else
return false
end
local object_type
local Collection = {}
Collection.__index = Collection
local collections = { turtle = "disk/db/turtle", computer = "disk/db/computer", chest = "disk/db/chest", }
local fenv = getfenv()
if turtle then
object_type = "turtle"
else
object_type = "computer"
end

local function checkInput(self, table)
if self == nil then
print("you must use this command like:")
print("db.collection_name:method_name(input)")
return false
elseif type(table) ~= "table" or table ~= false then
print("db::the input is not a table")
return false
end
return true
end

function Collection.create(path, type)
local collection = {}
setmetatable(collection, Collection)
collection.path = path
collection.type = type
return collection
end

function Collection:save(table)
if not checkInput(self, table) then
return false
end
if fs.exists(self.path.."/"..self.type.."_"..table.id) then
print("there is already a table for this, pelase use update function")
end
  local nTable = textutils.serialize(table)
  local file = fs.open(self.path.."/"..self.type.."_"..table.id, "w")
  file.write(nTable)
  file.close()
end

function Collection:update(table)
if not checkInput(self, table) then
return false
end
if not fs.exists(self.path.."/"..self.type.."_"..table.id) then
print("there isnt a table for this, pelase use save function")
return false
end
local reading_file = fs.open(self.path.."/"..self.type.."_"..table.id, "r")
local oTable = textutils.unserialize(read_file.readAll())
reading_file.close()
local nTable = oTable
for key,value in pairs(table) do
if type(table[key]) == "table" then
for k, v in pairs(value) do
if type(nTable[key]) ~= "table" then
					nTable[key] = {}
				end
nTable[key][k] = v
end
else
nTable[key] = value
end
end
local nTable = textutils.serialize(nTable)
local opened_file = fs.open(self.path.."/"..self.type.."_"..table.id, "w")
opened_file.write(nTable)
  opened_file.close()
end

function Collection:delete(id)
if not checkInput(self, false) then
return false
end
if not fs.exists(self.path.."/"..self.type.."_"..table.id) then
print("the file you're trying to delete doesn\'t exists ")
return false
end
fs.delete(self.path.."/"..self.type.."_"..id)
end

for key,value in pairs(collections) do
	if type(fenv[key]) ~= "table" then
		fenv[key] = {}
	end
	fenv[key] = Collection.create(value, key)
end

this is working (at least the save function)

i have this program to start_server and the problem is in here


Spoiler


while true do
local id, message, distance = rednet.receive()
message = textutils.unserialize(message)
if type(message) ~= "table" then
print("wrong format")
else
local tType = tostring(message['type'])
local table = message.table
local action = message['action']
if Ttype == "undefined" or table == "undefined" or action == "undefined" then
print("table incomplete")
else
table.id = id
db.tType:action(table)
end
end
end

db.tTYpe:action(table) doesnt seem to work because tType and action are strings… how could i work around this? (i need the : beacuase my api needs the self from local objects inside the api)
Goof #2
Posted 07 February 2013 - 08:33 AM
any errors?

ps:


while true do
local id, message, distance = rednet.receive()
message = textutils.unserialize(message)
if type(message) ~= "table" then
print("wrong format")
else
local tType = tostring(message['type'])
local table = message.table
local action = message['action']
if Ttype == "undefined" or table == "undefined" or action == "undefined" then -- on this line you defined Ttype wrong. (it should be tType)
print("table incomplete")
else
table.id = id
db.tType:action(table)
end
end
end

in my opinion that code should work… but im not so sure that i can promise it…

Try editing the Ttype, and then if you've got an error, post it here :D/>

I hope i can help.
Lyqyd #3
Posted 07 February 2013 - 10:35 AM
Looks like you may actually be trying to call:

db[action](db, db[tType], table)

Or some similar unholy monstrosity. What ARE you trying to do?

Or maybe you're trying for:

db[tType][action](db[tType], table)

I'm not really sure what you think that line should be accomplishing. Since what you're effectively doing is:

db.tType.action(db.tType, table)

But I very much doubt you have tType or action indices (since you're using them as string literals!) in your real tables. I definitely don't see an action function above, so I know you're indexing with that incorrectly.
corisco1917 #4
Posted 07 February 2013 - 03:46 PM
db[tType][action](db[tType], table)

indeed i want to call this but if i call this way i had to change my bd inplementation… there is no way to call with the : ?
theoriginalbit #5
Posted 07 February 2013 - 03:52 PM
db[tType][action](db[tType], table)

indeed i want to call this but if i call this way i had to change my bd inplementation… there is no way to call with the : ?
The : is implying that there is a function action on the db object, which there is not.
corisco1917 #6
Posted 07 February 2013 - 04:19 PM
db[tType][action](db[tType], table)

indeed i want to call this but if i call this way i had to change my bd inplementation… there is no way to call with the : ?
The : is implying that there is a function action on the db object, which there is not.

there is because of my implementation…the atribution of Colletion is local but it in :


for key,value in pairs(collections) do
	if type(fenv[key]) ~= "table" then
		fenv[key] = {}
	end
	fenv[key] = Collection.create(value, key)

it creates global objects for the colection… i can access _G["bd"]["turtle"] and it says its an table.
so when i call db.turtle:save(some_table) self works just fine… that's why i want to call with the :

ive test in lua console calling bd.turtle.save(table) and it works just fine, but i ned to implement the server call through rednet.receive()

i did like so because i don't want to expose collection.create() to outside of my API
corisco1917 #7
Posted 07 February 2013 - 04:33 PM
since i can't call a method with : with array like methods call ex: ([api][method]:[action](x)) i used loadstring like this:


table = textutils.serialize(table)
local func = "db."..tType..":"..action
assert(loadstring("return "..func.."("..table..")"))()

this way you are able to call string as methods with :

if you don't need to use :
you cloud call array like ex: [api][method][action](x) or
this post from stack overflow show's you how to call with with global:
http://stackoverflow...h-function-name

sorry if i didn't made my self clear, english is my secound language.