Thinking with Functions — Introduction
I’m a major contributor to ScriptingHelpers.org, which helps ROBLOX Lua programmers with problems with their programming.
Unsurprisingly, most of the submitted code isn’t “good style,” since the programmers are newer. A big key to this is that functions aren’t used.
What are functions?
In most modern programming languages, what are called “functions” are really a mix of two concepts:
Mathematical functions — you put one thing in, and you get one thing out. Square-root is a function. Dividing by two is a function. Taking the mean of a sequence of numbers is a function.
Procedures — sequences of actions. This essentially helps you “group” code together under a name, so that your code is easier to understand.
A quick review, for those not familiar with Lua. In Lua, functions look like this:
function name(argumentOne, argumentTwo)
name is the name of the function, arguments are the stuff coming in to the function, and the body is what the function does.
You call (use) a function like this:
name() -- No arguments
name(one) -- One argument
name(one, two) -- Two arguments
How do I use functions to make my code better?
Start by describing the whole thing of what you want to do. For example,
I want players to be given a particular uniform when they step on a block
Now, break it into the pieces of what need to be done:
Do this to any player that touches this block:
Remove their current Pants and Shirts
Give them this Pants and Shirt.
Now we know that we need (at least) three functions: dressPlayer, removeUniform, giveUniform. This makes the code very simple and clear:
for _, child in pairs(character:GetChildren()) do
if child:IsA("Clothing") or child:IsA("ShirtGraphic") then
local pants = Instance.new("Pants", character);
local shirt = Instance.new("Shirt", character);
if part.Parent and part.Parent:FindFirstChild("Humanoid") then
From the function names, it’s incredibly clear what each is supposed to be doing, and because the longest is four lines long, it’s also easy to read each and determine what they’re doing.
In other words, this is the wrong way to solve this problem:
if part.Parent and part.Parent:FindFirstChild(“Humanoid”) then
for _, child in pairs(part.Parent:GetChildren()) do
if child:IsA(“Clothing”) or child:IsA(“ShirtGraphic”) then
local pants = Instance.new(“Pants”, part.Parent);
local shirt = Instance.new(“Shirt”, part.Parent);
The first hint that the above is probably not an elegant solution is the name. partTouched doesn’t really say what is happening here — complicated things are happening, and we don’t really know is happening without reading carefully. Compare this version to the previous one, which just calls dressPlayer — and we know what was intended, without even writing any comments (though you should always do this too)!
List what you want to accomplish.
Give each small task its own function — use many short functions, not one (or zero) long ones.
Give your functions names that describe what they do.