Coercion

From Legacy Roblox Wiki
Jump to navigationJump to search

What is Coercion?

Lua performs automatic conversion of numbers to strings and vice versa where it is appropriate. In computer science, this is called coercion.

Lua will automatically convert the string and number types to the correct format in order to perform calculations. For example, if you try to apply an arithmetic operation to a string, Lua will try to convert that string to a number first, otherwise the operation will not work. If the string cannot be converted to a number an error is raised.

Examples:

print("This is Lua version " .. 5.1 .. " we are using.")
This is Lua version 5.1 we are using.
print("Pi: " .. math.pi)
Pi: 3.1415926535898
print("Pi: " .. 3.1415927)
Pi: 3.1415927

As shown above, during coercion, we do not have full control over the formatting of the conversion. To format the number as a string as we would like we can use the string.format() function. e.g.:

Example:

print(string.format("%.3f", 5.1))
5.100

Note how there are three decimal places.

print("Lua version " .. ("%.1f"):format(5.1))
Lua version 5.1

This is explicit conversion using a function to convert the number, rather than coercion.

Using Coercion

Something you must remember about coercion is that it should be avoided when possible. Just because it works doesn't mean it is good practice to use it. There's nothing wrong with not converting a number before sending it to a function that will still accept it anyways, for instance, but try to avoid coercion when you can.

print(100 + "7")
107
print("1000" + 234)
1234
print(234 + "1000")
1234
print("hello" + 234)
attempt to perform arithmetic on a string value

You can see where a string can be converted to number, the calculation succeeds. The string "hello" cannot be converted to a number and so an error occurs. In statically typed languages (e.g. C) this would cause an error as you cannot assign a value to a variable of an incompatible type. This works in Lua because it is dynamically typed.

A notable exception: comparison operators (== ~= < > <= >=) do not coerce their arguments. The (in)equality operators consider a number to be not equal to its string representation (or any non-number type in fact). Ordered comparison operators throw an error when you feed them different types:

print(100 == "100")
false
print(100 ~= "hello")
true
print(100 ~= {})
true
print(100 == tonumber("100"))
true
print(100 <= "100")
attempt to compare number with string

Coercion of Other Types

Coercion does not only exist for numbers and strings. There are also other cases of coercion that apply in ROBLOX.

Enums

One example is enums. When you use a string or a number where an enum or a number is expected, it is coerced to an enum.

Here are three examples that all do the same things, they all create a Part and make it Concrete:

Instance.new('Part', Workspace).Material = 816
Instance.new('Part', Workspace).Material = 'Concrete'
Instance.new('Part', Workspace).Material = Enum.Material.Concrete

TimeOfDay

Another example of coercion is with the TimeOfDay property of the Lighting. This property sets the current time in the server, which defines whether it is night, day, or any other time. The TimeOfDay property is a string, but, if you send it a number as argument, it will still work.

Here are two examples. One uses a number, and one uses a string. Both do the same thing:

game.Lighting.TimeOfDay = 5
print(game.Lighting.TimeOfDay)
05:00:00
game.Lighting.TimeOfDay = "05:00:00"
print(game.Lighting.TimeOfDay)
05:00:00

See Also