Issue with the ending of a function?

local numberValue = script.Parent
local function result()
	local timeout = false
	do
		spawn(function()
			local hasChanged = numberValue.Changed:Wait()
			if not timeout then
				print(1)
				timeout = true
				result()
			end
		end)
		delay(5,function()
			if not timeout then
				print(2)
				timeout = true
				numberValue.Value = 0
			end
		end)
	end
end
numberValue.Changed:Connect(result)

The following function looks whenever a numberValue has been changed and, checks for a next change within the 5 seconds and if no changes has been made, resets the numberValue’s value to 0. otherwise, keeps the numberValue to the same value and repeat the process (function itself).

I fortunately changed the numberValue’s value a few times, but I notice that the output prints the number 1 way more times than expected. It looks like some kind of factorial stuff, except that it’s doing the addition instead of multiplication as you can see below.
https://gyazo.com/b12d9474e8af837dcfe96e911dd27ea8

This is just a repro of an issue that I’ve been having with something more complex. I simplified it for the ease of understanding. Feel free to suggest any ideas.

1 Like

The sequence you are seeing (0, 1, 3, 6, 10, 15, 21, …) where each next term increases by the number of that term (3 + 3 = 6, 6 + 4 = 10, 10 + 5 = 15, 15 + 6 = 21) happens because each time you change the value, it repeatedly prints 1 the total number of times that the value has been changed. The first time it prints once, the second time it prints twice, etc. This is because every time result is called, it calls itself again after the value is changed, which is an infinite recursive loop.

1 Like

Oh, and is there a way to fix it because it doesn’t seem like I mean, I tried to return something, to disconnect it, but it’s still doing the same.

local numberValue = script.Parent
local function result()
	local timeout = false
	local hasChanged
	do
		spawn(function()
			hasChanged = numberValue.Changed:Wait()
			if not timeout then
				print(1)
				timeout = true
				hasChanged = hasChanged or hasChanged:Disconnect()
				delay(0.3,function()
					return 
				end)
				result()
			end
		end)
		delay(1,function()
			if not timeout then
				print(2)
				timeout = true
				numberValue.Value = 0
				hasChanged = hasChanged or hasChanged:Disconnect()
			end
		end)
	end
end
numberValue.Changed:Connect(result)

The problem is that result calls itself. You’ve introduced some new problems in that updated code. numberValue.Changed:Wait() doesn’t return a RBXScriptConnection so disconnecting it doesn’t make sense, and adding return inside a function in a delay call only returns that function it’s written in, resulting in nothing.

local numberValue = script.Parent
function result()
	local timeout = false
	local decision = nil
	local hasChanged
	do
		spawn(function()
			hasChanged = numberValue.Changed:Wait()
			if not timeout then
				print(1)
				timeout = true
				hasChanged = hasChanged or hasChanged:Disconnect()
				delay(0.5,function()
					decision = "clicked before" 
				end)
				return
			end
		end)
		delay(1,function()
			if not timeout then
				print(2)
				timeout = true
				numberValue.Value = 0
				hasChanged = hasChanged or hasChanged:Disconnect()
				decision = "late"
			end
		end)
	end
	if decision == "late" then
		print("restarting to 0")
	elseif decision == "clicked before" then
		print("nice job")
	end
end
numberValue.Changed:Connect(result)

I realized that the return was already inside something. My bad lol.

Just based on your description of what the code is supposed to do, you can keep track of how many times the value has changed and if that value is the same after 5 seconds, it hasn’t been changed.

local numberOfChanges = 0
numberValue.Changed:Connect(function()
	numberOfChanges = numberOfChanges + 1
	local oldNumberOfChanges = numberOfChanges
	wait(5)
	if numberOfChanges == oldNumberOfChanges then
		numberValue.Value = 0
	end
end)