Using logical operators in variable assignment

I’ve seen many people use logical operators(and, or, not) while assigning variables. I don’t understand how it works. I’ve searched around quite a bit but I can’t seem to find anything that explains how it works.
I read this while looking through a post regarding ledge climbing system:

surface = ((position - cframe.p).magnitude > (position - surfaces[surface].p).magnitude and surface or side)

Also this:

e = e < 3 and 3 or x < 0 and 0 or x

Could someone explain to me how it works?

They are called ternary operations and doing “e < 3 and 3 or x < 0 and 0 or x” is the same as “e = if e < 3 then 3 elseif x < 0 then 0 else x”. The “and” is like using “then” and the “or” is like a “else”. If you’re doing comparisons then a “if” will be infront of it. I don’t know exactly why “and” is used for ternary operations because the syntax sounds weird but for “or” it checks if the comparison is true or false, if it’s false then instead set it to the value at the right side of the “or”. You might have seen “or” get used in an example like this: local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait(). Here if the Character is nil then instead wait until character is added and give it that way. you can actually also use if statements for ternary operations but you can’t use “end” at the end of the if-statement. I’ve already shown an example for your e line of code. But for the character code it would look like this: local Character = if game.Players.LocalPlayer.Character then game.Players.LocalPlayer.Character else game.Players.LocalPlayer.CharacterAdded:Wait(). As you can see I don’t use any “end” because else you will get a syntax error. Ternary operations can help with saving lines but may ruin readability. I mostly use “and” and “or” instead of if statements though because i have heard some rumours that they are in some way slightly better for performance. I don’t think anyone has actually proven it though. Also, not is just used for well, inverting a value. If you do “not true” then it will really just be “false”. If you use not on a comparison then it’s just inverting the result of that comparison. You have to now use parenthesis though else Luau wont know if you’re trying to invert the first value of a comparison: local result = not true == false. ← this will not work and result an error. So do local result = not (true == false) instead. That’s pretty much the only thing “not” does. Edit: I forgot to tell this but if you’re just giving a value then it will set the variable to that value. So: local result = 5 > 4 and true or false. will be set to true obviously, because 5 is greater than 4.

4 Likes

First of all, you need to know the meaning of truthy and falsy.

Truthy means that the language considers the value as something that can make an if statement work - Every value, except false and nil, is truthy.

Falsy means that the language considers the value as something that will run the else part of an if statement. false and nil are falsy.

I will recap the logical operators so it’s easier to see the full picture.

The logical operators work with any value, not just booleans. An and takes two operands. Normally, we define an and as “if both of the operands are truthy, return a truthy value”. If the first operand is truthy, then the second must be truthy too, for the and to return a truthy value. There is an obvious shortcut to take there, that is, to return the second operand itself. The people who implemented Lua did take that shortcut.

If the first operand of and is falsy, then, the and should return a falsy value. Lua chooses to return the first operand, as that falsy value to return if the first operand is falsy. It won’t bother evaluating the second operand if the first one is falsy; we call that “short circuiting”.

or also has similar behavior - or also returns the last evaluated operand, but the way it short circuits is different. It doesn’t bother evaluating the second operand when the first is truthy, because the result is now confirmed to be a truthy value. If the first operand is falsy, it returns the second operand, which if you think about it, is supposed to be the result of the operation - if the second one is falsy, both are falsy, so return the falsy value.

So now let’s get to the actual question: How does that work?

The assignment isn’t special here, let’s focus on the expression. Let’s have 3 values; x, y and z.

x and y or z

Let’s focus on the and first. If x is truthy, evaluate to y. If it’s not, evaluate to x. There is an assumption made in this system, and it’s the main flaw of this system. y should be truthy for this to work. Thankfully it’s not the biggest assumption since the falsy values aren’t usually necessary in an expression like this one.

So, after the and, we either have the truthy y value, or if we don’t, we have x which is now confirmed to be falsy because it short circuited. If we have y, the or will short circuit, and we get y as the result. If we have x, the or will return z.

Therefore, it means: evaluate to y if x is truthy, z if not

What if y is falsy? Well, Luau, the Lua dialect used by Roblox, has an if expression which can be written as if x then y else z.

Sorry for creating this reply, I couldn’t see alliedoeihoialt’s reply because of my awesome and totally flawless internet. I kinda overcomplicated the thing as well, when I tried getting into the details, I stopped seeing the full picture I was trying to show.

What’s funny is that when I need to read code, I read ors as “x, or if it doesn’t exist, then evaluate to y” with “existence” being a synonym I use for truthiness (it’s not a correct synonym though)

4 Likes

That first snippet is an example of a ternary operator in Lua.
if Value1 and Condition or Value2
This would return ‘Value1’ if ‘Condition’ is truthy or ‘Value2’ if ‘Condition’ is falsy.
http://lua-users.org/wiki/TernaryOperator

1 Like

I remember doing some benchmarks comparing short-circuiting with Luau ternary operators and they’re basically the same in terms of performance. Even if there are differences, they are too small to matter in a practical sense. I would personally stick with using the proper ternary operators because of extra clarity (you know exactly what it means whereas a and b or c might confuse new developers who are not familiar with short-circuiting), and its explicit nature (it will always return the correct expression, whereas if b is falsey in a short-circuit expression, it will always return c).

This is from the official Luau documentation website:
image

5 Likes