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

How can I get a function to return a value that "doesn't exist"?

Hello,

I am attempting to make a dropdown list which will return the position of the selected value within the table it is provided. The function creates the dropdown list OK, and this was my rather abysmal attempt at returning the position of the selected option.

Now I know that at some point I need to get my local script to yield, and wait for a selection from the user.

I've hypothetically thought of a few ways of how to tackle this, perhaps the function could return a table with functions attached to each option - and then the local script would have to listen to each using multiple threads?

Regardless, I'm completely stuck and would appreciate any assistance.

Here's my module script:

function module.createDropdownList(element, options)
	for i, v in pairs(options) do
		local option = Instance.new("TextButton", element)
		option.Parent = element
		--stuff
		option.MouseButton1Click:connect(function()
			return i
		end)
	end
end

And my local script:

main:WaitForChild("create").airline.MouseButton1Click:Connect(function()
	selection = module.createDropdownList(main.create.airline, options)
	print(selection)
end)

This obviously, prints nil but I thought it would be useful in giving you an idea on how I would love this to work.

Thank you for your time!

1 comment

0

1 answer

✓ Accepted answer

If I understand you right, you want to be able to ask the user to pick from a set of options, and get what option they picked.

Blocking

Until they pick an option, you can't do anything, so it makes sense for the ask() call to block (wait) until an answer is back.

ie, ask should not return until it has its answer.

gui = script.Parent.Options

function ask(...)
	local answer = nil
	for i, option in ipairs{...} do
		local label = Instance.new("TextButton", gui)
		label.Size = UDim2.new(0.5, 0, 0, 32)
		label.Position = UDim2.new(0, 0, 0, 32*i)
		label.Text = option
		label.MouseButton1Click:connect(function()
			answer = option
		end)
	end

	repeat
		wait()
	until answer

	gui:ClearAllChildren()

	return answer
end

local choice = ask("yes", "no", "maybe")
print("user chose", choice)

Of course, this repeat wait() loop is wasteful. It would be better to use a real event and :Wait() for it. You can use a BindableEvent for that.

function ask(...)
	local event = Instance.new("BindableEvent")
	for i, option in ipairs{...} do
		......
		label.MouseButton1Click:connect(function()
			event:Fire(option)
		end
	end

	local answer = event.Event:Wait()
	gui:ClearAllChildren()
	return answer
end

Promise

Sometimes it's an annoyance that functions block (in particular if there's multiple things going on at once).

Instead, you want the function to return immediately, but you want to say "...but when I get an answer, do this".

Promises are what you can use when a value doesn't exist yet.

A "promise" is a way of doing this. You return an event, and the caller just :Wait()s or :Connect()s to that event to discover the choice of the user at a later time:

function ask(...)
	loca event = Instance.new("BindableEvent")
	for i, option in ipairs{...} do
		......
		label.MouseButton1Click:connect(function()
			gui:ClearAllChildren()
			event:Fire(option)
		end
	end

	return event.Event
end

local onChose = ask("yes", "no", "maybe")
onChose:Connect(function(choice)
	print("chose", choice)
end)
-- OR
print("chose", onChose:Wait())

Callback

Callbacks aren't the best, but they're another way to do this.

It's similar to a promise, except that instead of being returned the event, you give the function to be called with the answer, and return nothing:

function ask(action, ...)
	for i, option in ipairs{...} do
		......
		label.MouseButton1Click:connect(function()
			gui:ClearAllChildren()
			action(option)
		end
	end
end

2 comments

1

event:Wait() should actually be event.Event:Wait() but great answer.

0

You made a breaking typo, "loca Event" instead of local.

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