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

How does pcall, xpcall, and ypcall actually work? [closed]

Asked by 8 years ago

I've seen previously in the past the uses of the pcall variations; however, some don't appear to work, and sometimes, to me, they don't work (at all).

One usage I've seen is the following:

local player = game.Players.LocalPlayer

pcall(function()
    player.PlayerGui.ScreenGui.TextLabel.Text = 'String'
end)

Or, similarly, this:

local Player = script.Parent

pcall(function()
    Humanoid.Health = 0 -- How is that even supposed to work..?
end)

But one of the major issues is that it masks errors:

function printWrittenIncorrectly()
    printttt('Hi! :D')
end

pcall(printWrittenIncorrectly)

However, you can retrieve the data it masks by doing the following:

function printWrittenIncorrectly()
    printttt('Hi! :D')
end

local Fired, Error = pcall(printWrittenIncorrectly)

if not Fired then
    print(Error)
else
    print('Code fired!')
end

But this is only one of the uses I'm aware of that'll work properly; but even so, you have to do that to unmask the error it hid.

Back to my question: How does pcall, xpcall, and ypcall actually work?

0
What do you mean how does it work? It terminates your function rather than your script if there is an error. cabbler 1942 — 8y

Locked by EmbeddedHorror, JakyeRU, ForeverBrown, WideSteal321, and BlackOrange3343

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
12
Answered by 8 years ago
Edited 7 years ago

pcall

pcall takes a function as it's only argument, and runs it in protected mode (hence the name pcall, or protected call). It always returns two values. The first in which is a boolean that determines whether or not the code ran without error (needless to say, true meaning it ran without error, false meaning it didn't). The second value depends on the first one. If the code ran without error, the second value is whatever the function you passed to pcall returns. If it hit an error, the second value is a string that contains the error message. Example:

local returned, data = pcall(function()
    print("Hello world")
    return "Ran without error!"
end)

print(returned, data)

The example above would print true and "Ran without error!", since there's nothing wrong with our code. However, if I were to input something like this:

local returned, data = pcall(function()
    x("Hello world") -- Assuming 'x' doesn't exist
    return "Ran without error!"
end)

print(returned, data)

It'd print false and something along the lines of attempt to call x (a nil value).

xpcall

xpcall works the same way pcall does, except it allows you to handle the error message it (potentially) returns yourself, by passing a second function argument as a callback. It will return the same error message like pcall, but as an argument to your new callback. Here's an example:

local returned, data = xpcall(function()
    x("This will error")
end, function(err) -- Second function argument, with parameter that will represent the error message
    print("Error: ", err) -- Print "Error: " before the message
end)

print(returned, data)

This would work the same way as pcall, except it would read "Error: attempt to index x (a nil value)"

ypcall

As of now, ypcall is the exact same as pcall (according to the ROBLOX wiki). It exists, however, because pcall was never supposed to allow any form of yielding within it's function argument. ypcall on the other hand, was implemented as an exception to this limitation. Though, the rules have changed since then (see ypcall for more info)


Hope this helped, let me know if you have any questions.

0
Actually, I do have a question: like in the 2 codes I presented, how does pcall work that? And sometimes, it doesn't appear to fire the code, even though, like in example code 1, the assets are already there. Is there a reason it's like that? Especially for the second code? TheeDeathCaster 2368 — 8y
0
To note, for the first two examples, they would break the script either way; they both have an extra end parentheses. :P Good explanation otherwise. (C; TheeDeathCaster 2368 — 7y
0
Thanks, forgot to change that in the edit. Examples should be syntax error-free now! ScriptGuider 5640 — 7y
Ad