Page 1 of 1

Attempt to index global '' (a nil value)

Posted: Wed Jul 11, 2012 5:50 pm
by McFaddenP
I've just started with learning love so sorry if this is a stupid question. I have four files: a main.lua, a player. lua, a conf.lua, and a map.lua. I am working on collision detection around the window of the game so that the player cannot go past it by using basic lines saying that if the players x is less than 0, than the players x is equal to 0. Every time I run the game though it comes with the error, "Attempt to index global 'map' (a nil value).

Re: Attempt to index global '' (a nil value)

Posted: Wed Jul 11, 2012 7:47 pm
by furi

Code: Select all

map = {}
Put this on the first line in map.lua. This way, "map.collide" can exist.

Re: Attempt to index global '' (a nil value)

Posted: Wed Jul 11, 2012 8:00 pm
by Robin
Simple solution:
Change the name of map.collide to map_collide

Better solution:
First, add map = {} to the top of map.lua.

Then, replace every time you use map_collide by map.collide.

Re: Attempt to index global '' (a nil value)

Posted: Wed Jul 11, 2012 8:37 pm
by coffee
Deeper explanation.
Everytime you use a table you need to be sure that was initialized before it encounters some operation dealing that table. So before any table.variable use or a named function like table.dothing or table:dothing just table = {} before.

A good thing is to initalize in the top of respective file dealing operations with that table. Saying so it's a good thing to map = {} in top of map.lua, player = {} in top of player.lua and so on. So when you require "map" that "map" table is initialized without worries and you can do all map things at your will.

Re: Attempt to index global '' (a nil value)

Posted: Fri Jul 13, 2012 2:03 pm
by furi
Oh! You could also do this:

Code: Select all

map = {
	collide = function()
		player.x,player.y = math.max(player.x,0),math.max(player.y,0);
	end;
}
It looks cleaner, and is much more to-the-point. You can check out these links (Tables Math Library) for a little bit of help on the subject, and to help explain how math.max works. (In summary, it checks between all of the numbers you input and returns the largest. This way, if player.x is smaller than 0, it returns 0.) math.min does the exact opposite, as well, if you ever need that, too.

Here's a more sophisticated approach, with some failsafes, and allowing the input of any table:

Code: Select all

map = {
	collide = function(obj) --Usage: map.collide(player)
		if type(obj)=='table' and obj.x~=nil and obj.y~=nil then
			local xx,yy=tonumber(obj.x),tonumber(obj.y);
			if type(xx)=='number' and type(yy)=='number' then
				obj.x,obj.y = math.max(xx,0),math.max(yy,0);
			end
		end
	end;
}

Re: Attempt to index global '' (a nil value)

Posted: Fri Jul 13, 2012 3:23 pm
by Robin
I would remove those type checks and calls to tonumber in your second example.

If the rest of the code is decent, it won't be any different (because you would be sure you only called the function with the right tables, with the right data types). And if the rest of the code is that awful to make defensive coding like that necessary, it won't protect you from your game completely falling apart.

Re: Attempt to index global '' (a nil value)

Posted: Fri Jul 13, 2012 3:31 pm
by furi
Robin wrote:I would remove those type checks and calls to tonumber in your second example.

If the rest of the code is decent, it won't be any different (because you would be sure you only called the function with the right tables, with the right data types). And if the rest of the code is that awful to make defensive coding like that necessary, it won't protect you from your game completely falling apart.
I understand. I presented it as an option only because I personally take bad coding into consideration with functions.

Re: Attempt to index global '' (a nil value)

Posted: Sat Jul 14, 2012 10:27 am
by kikito
That is called defensive programming.

The only places I would use it is in a function that is to be used by someone I don't know (not myself, or my team). Typically, the entry point of a library is a good place to do some checks - new people approaching the library will get something more useful than a random "nil reference" error if they make a mistake.

But that mostly an exception. The the rest of the code I write (functions that are not/should not be accessed by the public) I don't use defensive programming and I don't recommend it. If someone knows how to use your code, that's you (or your team). Those "extra type checks" will just make your code longer and more difficult to read and maintain. Readability and succintness is much more important than avoiding those "extra errors" that you are not likely to commit anyway.