Slot System having an error

Hello, I am working on a notification module and I have seen this error where it will run perfectly the first time and when I run it again it will add it to the second one but after I run it again it simply doesnt detect that the second slot is occupied. It constantly just prints that it would create on slot one which I find quite weird. I was looking for some help thanks!

function notificationHandler:createNotification(header, body, timing)
	
	local Header, Body, Timing = header or ' ', body or ' ', timing or 5
	
	if Header == ' ' and Body == ' ' then
		warn('Header or Body field must be filled out.')
		return
	else
		
		if Occupied[1] and Occupied[2] and Occupied[3] then
			
			print('would add to queue')
			
		elseif not Occupied[1] and not Occupied[2] and not Occupied[3] then
			
			print('would add to slot 1')
			
			Occupied[1] = true
			
		elseif Occupied[1] then
			
			print('would add to slot 2')
			
			Occupied[2] = true
			
		elseif Occupied[2] then
			
			print('would add to slot 3')
			
			Occupied[3] = true
			
		end
		
		print(Occupied[1])
		print(Occupied[2])
		print(Occupied[3])
		
	end
	
end

This is a really weird way of organizing the array. Just use table.insert and table.remove, it’ll automatically organize your table

1 Like

Forgot to post the errors,
image

I’m not looking for neatness right now, If you truly think that having the table be more organized would fix it, I will try it, but to what I know that’s simply just an easier way of managing tables.

Organization IS the problem. The array is supposed to be ordered chronologically where new elements are appended to the end and the gaps from removing elements are automatically filled back in. What I’m saying is your method of doing this is redundantly complicated (which is likely why it’s not working) and probably not worth it either when Lua had already provided you with the necessary tools to do it.

Let me know if you need help using those aforementioned functions

1 Like

Would you be willing to send a code example cause I dont normally use table functions and I don’t have all the subfunctions memorized. That would be great if you could! :slight_smile:

Adding on, not a rewrite of the whole functions just how I would go about storing which slots are occupied and how to add a slot into it so the script recognizes that its occupied.

Alright, so table.insert will insert an element into an array. By default it will insert the element at the end of the table:

local t = {} --empty array
table.insert(t, 'a')
table.insert(t, 'b')
table.insert(t, 'c')
print(t)
--output
{
 [1] = "a",
 [2] = "b",
 [3] = "c"
}

You can specify where you want to insert the element and everything will be shifted to accommodate for the extra occupant:

local t = {'a', 'c', 'd'} --array has 3 indices
table.insert(t, 2, 'b') --insert a new element at the 2nd index
print(t)
--output
{
 [1] = "a",
 [2] = "b",
 [3] = "c",
 [4] = "d"
}
--array now has 4 indices instead of 3

table.remove uses the same principle. You use it to remove a specific element from the array, and everything will be shifted once again to remove any gaps.

local t = {'a', 'b', 'c', 'd'} --array has 4 indices
table.remove(t, 2) --remove the 2nd index
print(t)
--output
{
  [1] = "a",
  [2] = "c",
  [3] = "d"
}
--array now only have 3 indices

In case it wasn’t already made clear, this is vastly different from just setting table values. These table functions are designed to be used on ARRAYS, while simply just assigning the indices are to be used on hash tables (aka dictionaries). See the difference:

local t = {'a', 'b', 'c', 'd'} --array has 4 indices
t[2] = nil --forcibly remove the 2nd index
print(t)
--output
{
  [1] = "a",
  [2] = void, --there is a gap here!
  [3] = "c",
  [4] = "d"
}

The output is what you can call a malformed array, because there is a gap and the elements are no longer in order. This can bring all sorts of problems if your code depends on it being a proper array (i.e. using ipairs to iterate, trying to count the size of the array, etc.).


In your case, you can use table.insert to add in the new notifications, and table.remove to remove them. As for the 3-notification-limit, you can run a simple size check on the array (if #Occupied < 3 then) to make sure there is space.

1 Like

I went off what you said to my understanding and came out with a script looking like this.

When I ran the createNotification function it does the exact same thing, it runs through sets the first one, goes through sets the second one and then it keeps creating the second one. I am so confused why it still isnt working?

local Occupied = {}

function notificationHandler:createNotification(header, body, timing)
	
	local Header, Body, Timing = header or ' ', body or ' ', timing or 5
	
	if Header == ' ' and Body == ' ' then
		warn('Header or Body field must be filled out.')
		return
	else
		
		local occupied1, occupied2, occupied3, possible = table.unpack(Occupied)
		
		print(occupied1, occupied2, occupied3, possible)
		
		if occupied1 == nil and occupied2 == nil and occupied3 == nil then
			
			print('none are occupied, making 1')

			table.insert(Occupied, 1, true)
			
		elseif occupied1 == true then

			print('one is occupied, making 2')

			table.insert(Occupied, 2, true)

		elseif occupied2 == true then

			print('two is occupied, making 3')

			table.insert(Occupied, 3, true)	
			
		elseif occupied1 == true and occupied2 == true and occupied3 == true then

			print('all slots occupied, adding to queue')
			
		end
		
	 	occupied1, occupied2, occupied3 = table.unpack(Occupied)

		print(occupied1, occupied2, occupied3, possible)
		
	end
	
end

The errors you gave are not very enlightening. Module scripts are created once maybe your error is from assuming different require() means different variables. Since the Occupied array is never set to false in your code sample this seems to be running perfectly.

While it is important to know the difference between lua’s tables and arrays the example is shown directly indexing items which does not falter as an array or table. The catch is any table with the key [1] will be treated as an array, and only the operations #Occupied and ipairs(Occupied) would be affected by early truncation.

It would be good programming practice to use an array if they intend to greatly expand the amount of Occupied notifications, but for three entries it can be easier to grasp if manually inserted. Either flagging ‘dead’ entries or implementing a swap-remove would be needed to do a fully dynamic array implementation; both more technical than a fistful of if statements.

Edit: I forgot table.remove shifts elements down. It is simple to implement with table.remove, but still might not solve the problem.

I did not expect you to just substitute the assignment statements with the table functions. That’s quite literally against what I’m trying to say. The table functions are substitutes for basically your entire script. It should look something as simple as this:

function notificationHandler:createNotification(header, body, timing)
	local Header, Body, Timing = header or ' ', body or ' ', timing or 5	
	if Header == ' ' and Body == ' ' then
		warn('Header or Body field must be filled out.')
		return --skip code below if sanity check fails
	end

	if #Occupied < 3 then
		print('inserting to slot '..#Occupied + 1)
		table.insert(Occupied, true)
		return --skip code below if success
	end
	--the following code will only run when the slots are full
	print('all slots occupied, adding to queue')
end
1 Like

As from a scripter point of view here, the post creator is looking for help to understand what went wrong. They did not understand what you meant when they made the changes to the script therefore, they were confused on what to do.

Anyways, after reviewing upon the code and testing here is what I have created.

local Occupied = {
	
	Frame1 = false,
	Frame2 = false,
	Frame3 = false,
	
}

local Queue = {}

function module.createNotification(header, body, timing)
	if Occupied.Frame1 == false or Occupied.Frame2 == false or Occupied.Frame3 == false then
		if Occupied.Frame1 == false then
			Occupied.Frame1 = true
			
			print("One has been created.")
			
			-- # Create Notification Here
			local Item1 = {
				Frame = nil, -- When you're creating the notification set this to the frame
				Time = timing,
			}
			
			table.insert(Queue, Item1)
			task.delay(timing, function()
				if table.find(Queue, 'Item1') then
					table.remove(Queue, 'Item1')
					Occupied.Frame1 = false
					print("Removed from queue.")
				end
			end)
			
			return
		elseif Occupied.Frame2 == false then
			Occupied.Frame2 = true
			
			print("Two has been created.")
			
			-- # Create Notification Here
			local Item2 = {
				Frame = nil, -- When you're creating the notification set this to the frame
				Time = timing,
			}

			table.insert(Queue, Item2)
			task.delay(timing, function()
				if table.find(Queue, 'Item2') then
					table.remove(Queue, 'Item2')
					Occupied.Frame2 = false
					print("Removed from queue.")
				end
			end)

			return
		elseif Occupied.Frame3 == false then
			Occupied.Frame3 = true
			
			print("Three has been created.")
			
			-- # Create Notification Here
			local Item3 = {
				Frame = nil, -- When you're creating the notification set this to the frame
				Time = timing,
			}

			table.insert(Queue, Item3)
			task.delay(timing, function()
				if table.find(Queue, 'Item3') then
					table.remove(Queue, 'Item3')
					Occupied.Frame2 = false
					print("Removed from queue.")
				end
			end)

			return
		elseif Occupied.Frame3 == true then
			print("Cannot create due to there being 3 frames already in use.")
			return
		end
		
	end
end

workeeddd thank you so much !! <3333

1 Like