Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Why does a string return nil when sent to a module script?

Hello, I am trying to make an advanced Vehicle management system based on the UK railway signalling system.

This system utilises a 'block' style system which separates the vehicles into their own block. No block should have 2 vehicles in at a time, unless permitted by someone with authority.

The system I have scripted allows for multiple vehicles in a block using 'string.split', as it allows me to remove vehicles from the block, but keep others.

The problem I currently face is that when sending the string for the block to a module script, it returns nil.

The current system makes sure the train is in a block but using string.find. This is currently failing for the reason attempt to concatenate nil with string. This confuses me, as the part it is referencing is sent as a string.

This is the code in the module script.

signal_manager.network = {}


function signal_manager.addblock(block)
	signal_manager.network[block] = 'unoccupied'
end

function signal_manager:exitblock(block,train)
	wait(2)
	local find = string.find(signal_manager.network[block], ' '..train..' ')
	if find ~= nil then
		workspace.signals.update.Value = not workspace.signals.update.Value
		if signal_manager.network[block] == ' '..train..' ' then
			signal_manager.network[block] = 'unoccupied'
		else
			local outcomes = string.split(signal_manager.network[block], ' '..train..' ')
			signal_manager.network[block] = outcomes[1]..outcomes[2]
		end
	end
end

At the start of the server, signals add their required blocks to the table, setting it as 'unoccupied'

function signal_manager.addblock(block)
	signal_manager.network[block] = 'unoccupied'
end

When a train leaves a block, it searches in the listed block, and if it finds it, it removes it.

function signal_manager:exitblock(block,train)
	wait(2)
	local find = string.find(signal_manager.network[block], ' '..train..' ')
	if find ~= nil then
		workspace.signals.update.Value = not workspace.signals.update.Value
		if signal_manager.network[block] == ' '..train..' ' then
			signal_manager.network[block] = 'unoccupied'
		else
			local outcomes = string.split(signal_manager.network[block], ' '..train..' ')
			signal_manager.network[block] = outcomes[1]..outcomes[2]
		end
	end
end

The part that triggers leaving the block is here.

TPWS.Touched:Connect(function(trigger)
	if trigger.Name == 'trigger' and trigger.active.Value == true then
		if debounce == true then
			debounce = false
			local unit = trigger.Parent.Parent.Parent
			if unit.unitinfo.block.Value ~= '' then
				local block = unit.unitinfo.block.Value
				signal_manager.exitblock(block,unit.Name)
			end
		end
	end
end

The part unit.unitinfo.block.Value is a string value.

When I add print(block) into the module script, inside the exitblock function, it prints nil.

Could someone please help, this is causing me a lot of confusion.

Thanks.

1 answer

function signal_manager:exitblock(block,train)
	wait(2)
	local find = string.find(signal_manager.network[block], ' '..train..' ')

In this part of the function train is nil because in other function your are calling it like this:

signal_manager.exitblock(block,unit.Name)

See the difference? :exitblock is called with : because you made it function signal_manager:exitblock, you are calling it with ., that way you are not passing the self argument automatically so instead of normal self it uses first argument which in your case is block. Since you are not using self in exitblock function, you should not be calling it with :, but if you want it for some reason, you need to replace the first argument with a self, since as i said you don't use self in the function, the first argument can be any value, in your case just nil so you should call it like this signal_manager.exitblock(nil, block,unit.Name)

train in your case is nil but block refers to the train. block in this case is self and train is block because it removed the first argument due to not calling it with :.

What you really should do is just change

function signal_manager:exitblock(block,train)
	...

to

function signal_manager.exitblock(block,train) -- call with .
	...

I am not exactly sure why with print(block) it prints nil but i know this for sure so try it, it can fix it, just replace : with . and that's it.

2 comments

0

More importantly, the module doesnt actually return the functions.

0

If a function is expecting 'self', whether because it is defined with a ':' or because its first argument is explicitly 'self', don't call it with "nil", just call it with : (ie do signal_manager:exitblock(block, unit.Name) instead of signal_manager.exitblock(nil, block, unit.Name). Though passing 'nil' is okay at the moment, if the function ever needed to use 'self', you'd get strange bugs!

This discussion is preserved as it was. New answers, comments, and votes are closed.