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
7 years ago
Edited 7 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:

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!

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

1 answer

Log in to vote
7
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
7 years ago
Edited 7 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.

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
1
event:Wait() should actually be event.Event:Wait() but great answer. ScriptGuider 5640 — 7y
0
You made a breaking typo, "loca Event" instead of local. RubenKan 3615 — 7y
Ad

Answer this question