lua: why can't I use the name of the package? - lua

Based on SimpleLuaClasses I've done a class in a file:
require 'class'
Session = class(function(self)
self.session_name = "l_sid"
end)
function Session:init(r)
self.session_id = r:getcookie(self.session_name)
if not self.session_id then
self.session_id = r:sha1(tostring(r.log_id) .. r.clock())
r:setcookie({
key = self.session_name,
value = self.session_id
})
end
end;
Now I'm trying this:
local session = require 'session'
function handle(r)
local s = Session()
s:init(r)
end
The previous code works. If I try local s = session.Session() it doesn't work.
When I try this, I get this error:attempt to index upvalue 'session' (a boolean value).
Why?

The return value of the require function is the value returned from your module. For example, if you create a file "foo.lua" with the following contents
-- This is foo.lua
return 17
When you do in another file
local x = require 'foo'
print(x)
Its going to print 17.
In your case, in order to have session.Session work you would need to return a table with a Session field from "session.lua"
return { Session = Session }
Alternatively, you can also just return Session directly if you aren't returning anything else
-- in session.lua
return Session
-- in the other file
local Session = require 'session'
Finally, the reason your first sollution is working is that you are defining Session as a global variable, that is seen from every module. I would recommennt avoiding globals as much as possible so you can turn Session into a local in session.lua
local Session = class(function() ... end)
Compiling everything together, here is how your fiull session.lua file should look like
require 'class'
local Session = class(function(self)
self.session_name = "l_sid"
end)
function Session:init(r)
self.session_id = r:getcookie(self.session_name)
if not self.session_id then
self.session_id = r:sha1(tostring(r.log_id) .. r.clock())
r:setcookie({
key = self.session_name,
value = self.session_id
})
end
end;
return Session

Here's a version that works:
--[[
--------------------------------------------------------------------
Classe Session
]]--
require 'class'
local session = {}
session.Session = class(function(self)
self.session_name = "l_sid"
end)
function session.Session:init(r)
self.session_id = r:getcookie(self.session_name)
if not self.session_id then
self.session_id = r:sha1(tostring(r.log_id) .. r.clock())
r:setcookie({
key = self.session_name,
value = self.session_id
})
end
end;
return session

Related

ROBLOX LUA(u) Attempt to call a nil value on Database

I'm trying to make a DB and I'm still in testing phrase, but it doesn't work.
Basically the error is, I want it so if I type: ModuleScript:GetDB("salvage").Set("key", "value"), it would return a value, but it doesn't due to an error.
Any help is highly appreciated.
Error:
Photo
Server Script:
local ModuleScript = require(game.ServerStorage.ModuleScript)
game.Players.PlayerAdded:Connect(function(p)
p.Chatted:Connect(function(msg)
if msg == "t" then
print("lol")
print(ModuleScript:GetDB("salvage"))
ModuleScript:GetDB("salvage").Set("key", "value")
end
end)
end)
Module script:
--Variables
local dss = game:GetService("DataStoreService")
-- Tables
local greenwich = {}
local dbFunctions = {}
--Functions
function greenwich:GetDB(name)
local db = dss:GetDataStore(name)
local new = {}
new.store = db
coroutine.resume(coroutine.create(function()
for k, v in ipairs(dbFunctions) do
new[k] = function(...)
local args = { ... }
v(new.store, unpack(args))
end
end
end))
print(new.store.Name, name)
return new
end
function dbFunctions:Set(store, key, value)
print(value)
return value
end
--Returning everything.
return greenwich
Thanks in advance.
ModuleScript:GetDB("salvage") returns new which does not have a field Set so you cannot call ModuleScript:GetDB("salvage").Set("key", "value)
Set is a field of dbFunctions. You run a generic for loop over it using the ipairs iterator. dbFunctions is not a seqence, hence ipairs does not work for it. Use pairs instead.

I don't get Lua weak tables

Okay so I want to implement a cache generator, which returns a handle to me, but doesn't give me the actual data.
local module = {}
cache = {}
setmetatable(cache, { __mode = "k" })
function getItem(item)
local result = cache[item] or cacheItem(item)
return item
end
function cacheItem(item)
print("Caching item")
cache[item] = true
return cache[item]
end
function printCache()
for key, value in pairs(cache) do
print(key.name .. " and " .. value)
end
end
module.printCache = printCache
module.getItem = getItem
return module
But when I try to use it:
local module = require("./cache")
a = {
name = "Jimmie"
}
function foo()
local b = {
name = "Bobbie"
}
local h1 = module.getCachedItem(a)
module.getCachedItem(b)
local h3 = module.getCachedItem({ name = "Lenny" })
module.printCache()
end
foo()
module.printCache()
The first time around, I expect all names to be printed.
The second time around, I only expect "Jimmie" to be printed.
However all names are printed twice. lua -v returns 5.2.4.

Meta table error

I am trying to set up a toy example for threading in torch but I am getting an error from running the code below. I think it might just be the way I set up the table but I am not sure.
Threads = require 'threads'
Threads.serialization('threads.sharedserialize')
DataThreads = {}
DataThreads.__index = DataThreads
local result = {}
local unpack = unpack and unpack or table.unpack
function DataThreads.new(nThreads,opt_)
local self = {}
opt_ = opt_ or {}
self.threads = Threads(nThreads,
function()
print("background stuff")
end
)
self.threads:synchronize()
-- The below for loop is causing the error but the same :addjob() works later on
for i=1, nThreads do
self.threads:addjob(self._getFromThreads, self._pushResult)
end
return setmetatable(self,DataThreads)
end
function DataThreads._getFromThreads()
x,y = torch.uniform(),torch.uniform()
return x,y
end
function DataThreads._pushResult(...)
local res = {...}
if res == nil then
self.threads:synchronize()
end
result[1] = res
end
function DataThreads:getBatch()
self.threads:addjob(self._getFromThreads, self._pushResult)
self.threads:dojob()
local res = result[1]
result[1] = nil
if torch.type(res) == 'table' then
return unpack(res)
end
print(type(res))
return res
end
d = DataThreads.new(4)
The error occurs in :addjob() in the .new function. However calling the same :addjob() later on in the :getBatch() function works. Am I not allowed to call the ._getFromThreads(), ._getFromThreads() functions before the metatable is set? Here is the error, which I think means ._getFromThreads() is not returning anything;
/home/msmith/torch/install/bin/luajit: ...e/msmith/torch/install/share/lua/5.1/threads/threads.lua:215: function callback expected
stack traceback:
[C]: in function 'assert'
...e/msmith/torch/install/share/lua/5.1/threads/threads.lua:215: in function 'addjob'
threads.lua:21: in function 'new'
threads.lua:54: in main chunk
When the code in your new function runs the metatable hasn't been set up yet so when you use self._getFromThreads and self._pushResult there's nothing there and you get nil back and that's not valid.
It works after the new function returns because at that point the metatable has been added so the lookups use the __index metamethod to look the entries up.
You can do
local self = setmetatable({}, DataThreads)
to set the metatable up immediately and then just
return self
at the end.

Is This A lua Variable Scope Issue (and how can it be solved)?

A very strange error, showing an object is nil.
the code in subject is
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
...
One would think, that if pbs:HasNext() is true, it means that, pbs is not nil, whatsoever.
However, the print(pbs) - the first line of HTMLEntityCodec:DecodeCharacter prints nil
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
...
The entire file dumped below, it was stripped from 1800+ lines to 110 so it can be clear for SO users to get he context. But that stripping took away all logic from the code, so do not get confused by that.
#!/usr/bin/env lua
function Inherits( 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
-------------------------------------------
-- PushbackString
-------------------------------------------
PushbackString = Inherits({})
function PushbackString:Init(input)
self.input = input
self.pushback = nil
self.temp = nil
self.index = 0
self.mark = 0
end
-- Mark the current index, so the client can reset() to it if need be.
function PushbackString:HasNext()
return true
end
function PushbackString:Mark ()
self.temp = self.pushback
self.mark = self.index
end
BaseCodec = Inherits({})
function BaseCodec:Decode(input)
local buff = ''
local pbs = PushbackString:create()
pbs:Init(input)
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
if char ~= nil then
buff = buff .. char
else
buff = buff .. pbs:Next()
end
end
return buff
end
HTMLEntityCodec = Inherits(BaseCodec)
-- HTMLEntityCodec.classname = ('HTMLEntityCodec')
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
pbs:Mark()
end
DefaultEncoder = Inherits({})
function DefaultEncoder:Init(codecs)
self.html_codec = HTMLEntityCodec:create()
end
function DefaultEncoder:TestInput(input , strict)
print ("\n----------------8<----------------8<----------------\n")
print ("Input:\t" .. input)
-- default value
if strict == nil then strict = true end
-- nothing to do
if input == nil then return nil end
local working = input
local codecs_found = {}
local found_count = 0
local clean = false
while not clean do
clean = true
old = working
working = self.html_codec:Decode( working )
if old ~= working then
print ("Warning:\tINTRUSION DETECTED")
end
end
print ("Output:\t".. working)
return working
end
local default_encoder = DefaultEncoder:create()
default_encoder:Init()
default_encoder:TestInput("%25", true)
----------8<-----------8<--------------8<----------------
END OF FILE
Console Output:
tzury#1005:~/devel/lua$ lua problem.lua
----------------8<----------------8<----------------
Input: %25
nil
lua: problem.lua:70: attempt to index local 'pbs' (a nil value)
stack traceback:
problem.lua:70: in function 'DecodeCharacter'
problem.lua:54: in function 'Decode'
problem.lua:96: in function 'TestInput'
problem.lua:109: in main chunk
[C]: ?
In your code, the crash happens on this line:
local char = self.DecodeCharacter(pbs)
The problem is that you are calling DecodeCharacter with incorrect number of arguments.
Solution: call it like this (notice the colon):
local char = self:DecodeCharacter(pbs)
Explanation:
When you define functions in Lua using the colon (:), you are using a syntax sugar which hides an implicit first argument named self. Definitions like:
function HTMLEntityCodec:DecodeCharacter(pbs) ... end
Are actually 'translated' to this:
HTMLEntityCodec.DecodeCharacter = function (self, pbs) ... end
When you call the function, you either need to pass the self argument yourself, or use the colon call to supply it automatically. In your code (self.DecodeCharacter(pbs)), you are passing pbs which ends up as self in HTMLEntityCodec.DecodeCharacter, and pbs ends up being nil. Both following calls are equivalent and should solve the issue:
local char = self.DecodeCharacter(self, pbs)
local char = self:DecodeCharacter(pbs)

why doesnt my lua class implementation work?

I have implemented OOP in my lua environment but it doesnt seem to be working.
I think it has something to do with how i am handling the __index and my improper use of require and module but I'm not 100% sure.
Here is the code:
Class = function( prototype )
local derived = {}
local derivedMT = {
--When indexing into a derived class, check the base class as well
__index = prototype,
--When invoking a class, return an instance
__call = function( proto, ... )
local instance = {}
local instanceMT = {
--When indexing into an instance, check the class hierarchy as well.
__index = derived,
--Calling instances is a no-no!
__call = function()
print( "WARNING! Attempt to invoke an instance of a class!" )
print( debug.traceback() )
return instance
end,
}
setmetatable( instance, instanceMT )
if ( instance.__constructor ) then
instance:__constructor( ... )
end
return instance
end,
}
setmetatable( derived, derivedMT )
return derived
end
And here is how I use it, the nil reference is a call to a base class function, that is the error/problem im having is it seems like the base class isn't being referenced.
require "Core.Camera.FreeCamera"
local T = Core.Camera.FreeCamera.FreeCamera(0,0,-35)
c = T:getObjectType() -- nil reference
print(c .." --Type" )
and here is Camera.lua the base class
local _G = _G
module(...)
local M = _G.Class()
Camera = M
function M:__constructor(x,y,z) --This never gets called.
--self.Active = false
--self.x = x
--self.y = y
--self.z = z
--self.ID = EngineManager:getCamera()
print("InCameraInstance_-_-_-_-_-__-_--_-__-_-_-_--_-_-_-_-_--_-_-_--_--__-_---_--_---__-")
end
function M:getObjectType()
return "camera"
end
And Finally Free Camera which attempts to inherit Camera.
local require = require
local _G = _G
module(...)
require "Core.Camera.Camera"
local M = _G.Class( _G.Core.Camera.Camera ) --Gross, lame might be the culprit
FreeCamera = M
function M:__constructor(x,y,z) ---WHOOPS, this does get called... the other one doesnt
self.Active = false
self.x = x
self.y = y
self.z = z
self.ID = _G.EngineManager:getCamera()
--_G.print("got Id of:" .. self.ID)
self:setCameraPosition(x, y, z, self.ID)
_G.print("<<<Camera in lua>>>")
end
I'm running out of ideas. any help would be appreciated.
Instead of:
local M = _G.Class( _G.Core.Camera.Camera )
you need to have:
local M = _G.Class( _G.Core.Camera.Camera.Camera )
First Camera is the directory name, second is the module name, third is the class name.
Edit: You can clean it up a bit like this:
local CameraModule = require "Core.Camera.Camera"
local M = _G.Class( CameraModule.Camera )

Resources