Table setting itself to nil

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Table setting itself to nil

Post by BlackBulletIV »

I've got a class (I'm using MiddleClass) called Entity which initialises a table local to the file called _private. Here's the initialize() function:

Code: Select all

local _private = {}

function Entity:initialize()
    -- settings
    self.x = 0
    self.y = 0
    self.active = true
    self.visible = true
    
    -- tables
    self.tags = {}
    self.graphics = {}
    
    -- parent/child stuff
    self._parent = nil
    self._children = {}
    
    -- general objects 
    self._world = nil
    
    -- private stuff for the entity linked lists
    self._updateNext = nil
    self._updatePrev = nil
    self._drawNext = nil
    self._drawPrev = nil
    
    _private[self] = {}
    _private[self].layer = nil
end
When I print out the value of _private[self] it says it's a table. Now when I call a function called setLayer() on the same entity object, it says that I'm trying to index a nil value _private[self]. Here's the function:

Code: Select all

function Entity:setLayer(layer)
    if not layer then
        _private[self].layer = nil
        return
    elseif layer == _private[self].layer then
        return
    end
    
    _private[self].layer = layer
    self:getLayer()._entities:push(self)
end
Why on earth does it set _private[self] to nil?!? There is nothing in my code that resets it. By the way, here's the function that calls setLayer():

Code: Select all

function World:add(...)
    for _, v in ipairs(arg) do
        if not v._world then -- if it's not already added
            v._world = self
            _private[self].updateList:push(v)
            v:setLayer(_private[self].layers[1]) -- set to the default layer
            v:added()
        end
    end
    
    _private[self].count = _private[self].count + #arg
end
Can anyone help me out here? Thanks in advance.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Table setting itself to nil

Post by Robin »

On which line does it error exactly?
Help us help you: attach a .love.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Table setting itself to nil

Post by kikito »

Does it still happen if you stop using _private and just add a _layer method to Entities?
When I write def I mean function.
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Table setting itself to nil

Post by BlackBulletIV »

Robin wrote:On which line does it error exactly?
This line inside of the setLayer() function:

Code: Select all

    elseif layer == _private[self].layer then
Which is the line where _private[self] is first indexed.
kikito wrote:Does it still happen if you stop using _private and just add a _layer method to Entities?
No it actually doesn't give me any errors if I use self._layer. I'm still not getting the result I want (probably the result of some other bug; I write a lot of those things), but it doesn't give me errors.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Table setting itself to nil

Post by kikito »

BlackBulletIV wrote:No it actually doesn't give me any errors if I use self._layer. I'm still not getting the result I want (probably the result of some other bug; I write a lot of those things), but it doesn't give me errors.
It looks like it. Just to confirm: Neither middleclass, LÖVE or Lua do anything special with _private; for them it's just a regular variable - there's no way for it to magically 'set itself to nil'. It's almost certain that there's a bug somewhere.

If I may give you some advice, I think it will help you find this bug if you trim down your code first. For instance - this method:

Code: Select all

function Entity:setLayer(layer)
    if not layer then
        _private[self].layer = nil
        return
    elseif layer == _private[self].layer then
        return
    end
   
    _private[self].layer = layer
    self:getLayer()._entities:push(self)
end
Could be refactored to this:

Code: Select all

function Entity:setLayer(layer)
  self._layer = layer -- I'm assuming you are using _layer instead of _private now
  if layer then layer:addEntity(self) end -- new method on Layer, called addEntity
end
Then I'd make the Layer class deal with Entity addition / removal:

Code: Select all

function Layer:addEntity(entity)
  if not self:hasEntity(entity) then self._entities:push(entity) end
end
function Layer:hasEntity(entity)
  for _,e in self._entities do
    if e==entity then return true end
  end
  return false
end
Splitting the code into smaller methods like this will help you find bugs more quickly.

Regards!
When I write def I mean function.
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Table setting itself to nil

Post by BlackBulletIV »

I know it's a bug, it just "appears" to set itself to nil.

Yeah that's probably good advice. And your refactoring suddenly made me realise the pointlessness of:

Code: Select all

if not layer then
    _private[self].layer = nil
    return
But yeah, I might shift some of the management to the layer. Just a quick question, wouldn't adding another layer of function calls add a slight overhead? I'm used to ActionScript where it does.

Thanks for your help!
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Table setting itself to nil

Post by Robin »

BlackBulletIV wrote:Just a quick question, wouldn't adding another layer of function calls add a slight overhead?
Yes it will, just like Bill Gates is richer than before if you give him a dollar.
Help us help you: attach a .love.
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Table setting itself to nil

Post by BlackBulletIV »

Ha ha ha, nice one. Well that's good then.

By the way, I found the bug. It was as simple as it could get, I was passing in a reference to my class, rather than a reference to an instance of the class. This means that I was effectively doing this:

Code: Select all

_private[nil].layer
As self did not exist. I really do like dynamic languages, but sometimes the lack of types and heavy duty error raising can cause a lot goose chasing. Thanks again for help guys!

EDIT: Does anyone know if there's some sort of "strict" mode with Lua, where it would raise errors about things it would normally let go?
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Table setting itself to nil

Post by vrld »

BlackBulletIV wrote:Does anyone know if there's some sort of "strict" mode with Lua, where it would raise errors about things it would normally let go?
Yup, there is. In fact, there are several ways to detect undefined variables: http://lua-users.org/wiki/DetectingUndefinedVariables
A very simple method is presented in the lua book: http://www.lua.org/pil/14.2.html
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Table setting itself to nil

Post by BlackBulletIV »

Ah thanks for those.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 59 guests