I’ve been digging into this topic for an hour now, and ended up down two very different rabbit holes.
I have the sample code of:
function foo(bar : string) end
… and I’m unfamiliar with what the colon semantically represents. Whilst I’m not allowed to link the sources, one site I found suggests that it’s just sugar syntax when declaring a function as a child of a table, so that the self parameter doesn’t have to be hard-coded in the function’s syntax…
… whereas a different source (albiet in Python), suggests that this is function annotation for ease in typechecking params and returns in functions. I’d be inclined to believe this given the parallel syntax between to two, but when I try to modify the above sample code to something like this:
function foo(bar)
bar: string
end
… the program throws the error of:
function arguments expected near 'end'
I’ve got a fair amount of experience in programming, but I’ve never run into anything like this. Could some kind soul please explain this to me like I’m completely new to programming, or point me at a resource I can get my teeth into?
Just has a quick glance over the Forum Rules and saw that off-site posting was prohibited (bar a few whiltelisted sites) and thought it better to err on the side of caution.
This is an almost correct example of a function, the correct one would be
function foo(bar)
--insert code here
end
You dont actually have to but “bar :string” in there, it’s telling you that it uses a string for the argument “bar”
this code here employs the correct usage of the function, but it returns error because string is not supposed to be there, you’re supposed to define, here’s an example.
function foo(bar)
print(bar) -- This will print the string that was given when the function is runned
end)
No, using two colons instead of one tells the type checker to assume that the set value is a certain type.
Using one colon for function parameters and making new variables tells the type checker the the set value is expected to be the same as the given type of the variable:
local String : string -- Value expected to be a string value.
String = "hi" -- Good
String = CFrame.new(1, 2, 3) -- Bad
local Something -- Can be any type.
local Thats_A_Number = Something :: number -- Assumes Something is a number.
local function Function(Parameter : Vector3) -- Parameter is expected to be a Vector3.
-- do things
end
Function(Vector3.new()) -- Good
Function(20) -- Bad
Type-checking doesn’t mean (at least in Roblox) your code will error when given a different type, it only happens on how you use that type. So, instead of adding extra typeof() and assert lines to your code or having to read the functions itself to understand what it accepts, type check will instead show what type you must enter while adding in parameters:
-- Let's say function Teleport expects two parameters: Player instance, and a CFrame value.
-- Instead of...
local function Teleport(Player, CF)
assert(typeof(Player) == "Instance", "Player not an Instance")
assert(typeof(CF) == "CFrame", "CF not a CFrame")
assert(Player:IsA("Player"), "Player is not a Player class")
-- do stuff
end
-- You can...
local function Teleport(Player : Player, CF : CFrame)
-- Do Stuff
end
-- This function will still error if the wrong types are given, but the autocomplete feature should tell you the parameters' expected types.
Thank you very much, that explains everything that I was confused about.
Before, I assumed that by passing parameters with colons after them within functions, you were referencing the location of another variable, or comparing them (similar to an equality check, just evaluated before the function “starts”, so to speak).
Your post clears things up a great deal - thank you for taking the time to explain it to me!