Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
3

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

Asked by
ausmel105 140
8 years ago
Edited 8 years ago

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:

01function module.createDropdownList(element, options)
02    for i, v in pairs(options) do
03        local option = Instance.new("TextButton", element)
04        option.Parent = element
05        --stuff
06        option.MouseButton1Click:connect(function()
07            return i
08        end)
09    end
10end

And my local script:

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

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!

0
You can use this api http://wiki.roblox.com/index.php?title=API:Class/RbxGui/CreateDropDownMenu from the RbxGui library User#5423 17 — 8y

1 answer

Log in to vote
7
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago
Edited 8 years ago

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.

01gui = script.Parent.Options
02 
03function ask(...)
04    local answer = nil
05    for i, option in ipairs{...} do
06        local label = Instance.new("TextButton", gui)
07        label.Size = UDim2.new(0.5, 0, 0, 32)
08        label.Position = UDim2.new(0, 0, 0, 32*i)
09        label.Text = option
10        label.MouseButton1Click:connect(function()
11            answer = option
12        end)
13    end
14 
15    repeat
View all 25 lines...

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.

01function ask(...)
02    local event = Instance.new("BindableEvent")
03    for i, option in ipairs{...} do
04        ......
05        label.MouseButton1Click:connect(function()
06            event:Fire(option)
07        end
08    end
09 
10    local answer = event.Event:Wait()
11    gui:ClearAllChildren()
12    return answer
13end

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:

01function ask(...)
02    loca event = Instance.new("BindableEvent")
03    for i, option in ipairs{...} do
04        ......
05        label.MouseButton1Click:connect(function()
06            gui:ClearAllChildren()
07            event:Fire(option)
08        end
09    end
10 
11    return event.Event
12end
13 
14local onChose = ask("yes", "no", "maybe")
15onChose:Connect(function(choice)
16    print("chose", choice)
17end)
18-- OR
19print("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:

1function ask(action, ...)
2    for i, option in ipairs{...} do
3        ......
4        label.MouseButton1Click:connect(function()
5            gui:ClearAllChildren()
6            action(option)
7        end
8    end
9end
1
event:Wait() should actually be event.Event:Wait() but great answer. ScriptGuider 5640 — 8y
0
You made a breaking typo, "loca Event" instead of local. RubenKan 3615 — 8y
Ad

Answer this question