Avoiding Singletons in Lua

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
Jmaa
Prole
Posts: 8
Joined: Thu Feb 12, 2015 7:42 pm

Avoiding Singletons in Lua

Post by Jmaa »

Yada, first post, yada yada.

I love lua and love, but I have recently begun worrying about the extensive usage of singletons in lua and love.
Now, I know this is not that large of a problem, but it is an annoying security concern to me, as my programs often are built as platforms or systems for third party code, and I would rather avoid some random plugin calling a function that completely destabilises the program.

Now, I do understand that constants are a huge thing within lua, what with the local keyword being a thing, instead of global, but it really irritates me that locals defined outside functions really just are globals.

Are there any (relatively simple) ways to avoid singletons/constants in lua? (Outside doing some dumb redefining at top level, like moving stdlib stuff into the love namespace, which would not solve plugins calling the love namespace itself.)
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Avoiding Singletons in Lua

Post by Robin »

I'm not sure what you mean by singletons, because I can't think of any singletons used by either Lua or LÖVE.

If you mean the Lua standard library and the love table, you could place plugins in a sandbox, which would be a good idea anyway if they are untrusted.
Jmaa wrote:it really irritates me that locals defined outside functions really just are globals.
Top-level locals are local to the module, not global, btw.

Are there any (relatively simple) ways to avoid singletons/constants in lua? (Outside doing some dumb redefining at top level, like moving stdlib stuff into the love namespace, which would not solve plugins calling the love namespace itself.)[/quote]
Help us help you: attach a .love.
Jmaa
Prole
Posts: 8
Joined: Thu Feb 12, 2015 7:42 pm

Re: Avoiding Singletons in Lua

Post by Jmaa »

Robin wrote:I'm not sure what you mean by singletons, because I can't think of any singletons used by either Lua or LÖVE.
I am possibly just using a very wide definition of singleton, e.g: Everything involving a shared state, accessible everywhere.
Robin wrote:If you mean the Lua standard library and the love table, you could place plugins in a sandbox, which would be a good idea anyway if they are untrusted.
Well, just when I though I had reached the end of lua's greatness, another feature appears on the horizon. Thanks!
Robin wrote:Top-level locals are local to the module, not global, btw.
Huh, that explains some of the errors I got previously, good to know.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Avoiding Singletons in Lua

Post by s-ol »

I think Robin covered everything, so just a small heads-up: "singleton" is a very specific OOP term that has no relevance in lua. Singletons don't have to be Globally accessible, their only criteria is to only ever have one instance. A class library might implement a system for singletons (though that would be useless as hell - you can just throw some values and functions in a table and call it a day) there is nothing like that in "vanilla" lua or löve.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
Muris
Party member
Posts: 131
Joined: Fri May 23, 2014 9:18 am

Re: Avoiding Singletons in Lua

Post by Muris »

Locals are only valid after declaring, and a variable or function that is local on one lua file, cannot be accessed from other lua-file, except if you use function and return it.

The way how I use globals or I guess its quite close to singleton is by using a table called GLOBALS, and I define it in GLOBALS.lua which I require from main.lua. Inside this I probably put some even unnecessary things such as screen width and screen height + lots of other stuff. I am not sure if this is a good way to handle it, but at all my globals should be inside same table so it makes debugging at least a slightly easier, when _G stays a bit more clean.

You can "lock" your global table, so that if you make global it will cause an error. This would prevent accidental declarations of globals, but you can still use the GLOBALS-table and define new values inside GLOBALS-table even with the lock being on:

Code: Select all

GLOBALS = {}

setmetatable(_G, {
		__newindex = function (_, n)
    error("attempt to write to undeclared variable "..n, 2)
      end,
    __index = function (_, n)
    error("attempt to read undeclared variable "..n, 2)
		end,
})

GLOBALS.a = 1 -- works, no error thrown

print(GLOBALS.a)

function plaah() -- this will throw an error
end
b = 3 -- this will throw an error
The above metatable thing wasn't my own code, I found it from here: http://www.lua.org/pil/14.2.html

In the link there is also a method on how to make global variables even after defining the _G table again.
Like this:

Code: Select all

GLOBALS = {}

function declare (name, initval)
		rawset(_G, name, initval or false)
end

setmetatable(_G, {
		__newindex = function (_, n)
    error("attempt to write to undeclared variable "..n, 2)
      end,
    __index = function (_, n)
    error("attempt to read undeclared variable "..n, 2)
		end,
})

GLOBALS.a = 1 -- works

print(GLOBALS.a)

declare( "plaah", function() print "yo" end )
declare( "b", 3 )

plaah()
print(b)
User avatar
nfey
Citizen
Posts: 63
Joined: Tue Feb 18, 2014 9:50 am
Location: Romania

Re: Avoiding Singletons in Lua

Post by nfey »

Well, considering that you have to jump through hoops to work with objects in Lua, it's pretty easy to avoid singletons :P
There isn't really a wide or narrow definition of singletons - it's pretty straightforward, as far as design patterns go: https://en.wikipedia.org/wiki/Singleton_pattern . It's basically a class that has a private constructor in order to control the number of instances that can be out in the wild at any given point, coupled with a static member that holds the reference to that one instance. This way you can access the same (single) instance of a class from any point of the application. And if you're wondering, there are some subtle differences between a singleton implementation, a static class and having a static instance of a normal class. But this really makes sense in an object-oriented environment, it's not a solution suitable for Lua because Lua doesn't present the problems that the singleton addresses.

I think what you mean is avoiding static global variables. And you can avoid them by declaring everything local at the module level. And making a conscious effort not to rely on globals in general.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 77 guests