Pcall(), xpcall() and ypcall() Tutorial - How do they work?

Welcome curious Developers!

In this tutorial, I’ll be explaining how pcall() and xpcall() functions work and what happened to ypcall().

Let’s start

pcall()

pcall() is short for P rotected Call , if the code inside of this function has an error it will yield until the attached function run without any issues and won’t stop the rest of the script. It also returns two values: A bool one and a variant one.

local boolValue, variantValue = pcall(function() -- 1
    -- this code is protected
end)
  1. Naming the bool and the variant value, attaching pcall() to anonymous function.

The bool value is true when the function attached to pcall() ran without any issues, otherwise, it’s false; the variant value is a bit more complicated but let me explain as well as I can. When the bool value is false (error in the code), the variant value will contain the error that can be displayed with orange text in output using warn() function.

local boolValue, variantValue = pcall(function()
    -- this code is protected
    return 'hi' -- 1
end)

if boolValue == false then -- 2
    warn(variantValue) -- 3
else
    print(variantValue) -- 4
end
  1. Explained below
  2. Checking if there was an issue in the script.
  3. This function will be executed when bool is false
  4. This function will be executed when bool is true
warn()

warn() is like print() but print() writes information in the output and warn() writes warning which have orange text color.

But what will happen when the code inside the function doesn’t have any issues? If you don’t use return procedure the variant variable will return nil. You can use the return function if you want to store data from the script into the universal variable.

local successed, errData = pcall(function()
    print(1)
    print(2)
    print(3)
    return "string" -- 1
end)

print(errData)

-- Output:
-- 1
-- 2
-- 3
-- 'string'
  1. You can too return other values.

Use of pcall()

The most popular use of pcall() is data storing because functions like GetAsync() or SetAsync() are network calls and they can generate an error. pcall() is the best option in this case.

xpcall()

It’s better than pcall() (at least for me) because you can customize the error handler and it’s not yielding , if you know Python you can compare it to try-except block but xpcall is more universal. You have to provide 2 functions and if the first one “fail” the second one will run.

local successed, returnedData = xpcall(function()
    -- protected code
end, function() -- 1
    print('there is an error')
end)
  1. This function will run when the previous function got an error, simple right?

ypcall()

Short for “Yielding Protected Call”. Sometime pcall() wasn’t yielding and then ypcall() was useful but now pcall() is yielding too and this is the same thing so ypcall() is just deprecated and you should not use it anymore.

The End

I recommend reading Lua Globals because there is a short description for some functions and variables (for pcall() and xpcall() too), the rest is in Roblox Globals. That was my first community tutorial in DevForum, hope it’s understandable because English isn’t my strong point. I’d be happy if you give your opinion.

Thanks for reading , have a nice day! :smiley:

94 Likes

Except that wouldn’t create an error because calling a function like that is valid syntactically. It is the equivalent of this: print({'hi'})

7 Likes

ypcall global still exist in Luau but it’s deprecated as now pcall actually yields the code when called. In fact, both ypcall and pcall literally point to the same function.

3 Likes

How does this tutorial differ from this other one? ReturnedTrue’s tutorial seems to go more in depth and even explains when using the functions would be more preferable.

This is incorrect, types are not first class therefore cannot be returned by functions, passed around as arguments, etc. I believe you meant you can return any value of any datatype.

4 Likes

Is it me or is anyone experiencing this issue? When you call that function with pcall, roblox studio seems to error and crash. I can’t seem to find a way to use that line without studio crashing

1 Like

@BenMactavsin, @sjr04 and @BuildingRobloxUnited thanks for support. I updated the tutorial so hope it’s now correct.

not sure if you care, but the title has bad grammar

you said “How they works”

Thanks for report, “How they work” is fine?

2 Likes

since it is a question
“How do they work?”
would fit better

1 Like

I think it’s best practice to use pcall and ignore xpcall, but that’s just my opinion.
(Do not use ypcall as it is deprecated!!!)

I’ve tried a few benchmarks to test the performance differences:
(The functions are empty, otherwise the results won’t be significantly different)

--!strict
local Table: {
	Example: (self: any, Value: any) -> (),
	ErrorExample: (self: any, Value: any) -> (),
} = {
	Example = function(self, Value: any): ()

	end,
	ErrorExample = function(self, Value: any): ()
		error("En error occurred")
	end,
}
local function OnError(ErrorMessage: string): ()
	
end

local function TEST_pcall(Message: string, Function: any): ()
	local Start: number = os.clock()
	for n = 1, 100000 do
		local Success, Result = pcall(Function, Table, n)
		if not Success then
			OnError(Result)
		end
	end
	local End: number = os.clock()
	print(`{Message} {End - Start} seconds`)
end
local function TEST_xpcall(Message: string, Function: any): ()
	local Start: number = os.clock()
	for n = 1, 100000 do
		xpcall(Function, OnError, Table, n)
	end
	local End: number = os.clock()
	print(`{Message} {End - Start} seconds`)
end

TEST_pcall("pcall without error ", Table.Example)
TEST_xpcall("xpcall without error", Table.Example)
TEST_pcall("pcall with error    ", Table.ErrorExample)
TEST_xpcall("xpcall with error   ", Table.ErrorExample)

pcall would relatively be a bit faster when there are no errors occurring.
pcall would relatively be a little bit faster when there are errors occurring.
afbeelding

I’ve tried it multiple times and results are approximately the same.

The difference is not significant enough to mind it unless you need lots and lots of calls, then my guess is that pcall is the better choice.

In general, it’s up to you whether you use pcall or xpcall, whichever you find more comfortable to work with.

5 Likes