I'm having trouble understanding how the expressions ""==true and ""==false both evaluate to false.
Trying the following in the lua interpreter and ilua result in the same output:
> =""==true
false
> =""==false
false
Or executing the following:
print(""==true)
print(""==false)
print(""==nil)
Outputs
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
false
false
false
>
Another example:
> =""~=true
true
> =""==false
false
When the following code is run:
if "" then -- if ""==true
print "was true"
end
if not "" then -- if ""==false
print "was not true"
end
The output is (seemingly inconsistently)
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
was true
>
As expected per the Lua FAQ which states
C-like languages regard 0 as equivalent to false, but this is not true
for Lua. Only an explicit false or nil are equivalent to false. When
in doubt, make the condition explicit, e.g. if val == nil then ... end
unless the value is actually boolean.
How can a value be not equal to true,false or nill?
All Lua values when used as Booleans evaluate to true, except nil and false. This does not mean that values that evaluate to true are equal to true. If you want to convert a value v to Boolean, use not not v.
The type of "" is string, not boolean, so it's not equal to either true or false.
To be more general, when Lua compares two values, it tests their type first, if the type mismatch, Lua thinks the two values as not equal immediately.
When used as control expression, the only false values in Lua are false and nil, everything else is evaluated as true value. Some popular confusions include the number 0, the empty string "", the string "0", they are all true values. Note again that false and nil are not equal because they are different types.
So back to the example, in the code
if "" then -- if ""==true
print "was true"
end
Lua tests if "" is false or nil, since it's neither, then Lua treats the condition as true value.
Disclaimer: I have no experience with lua, this is an educated guess
This is probably because "" is an empty string, so Lua probably evaluates it as a string with length of zero. Since it's a valid object it's not going to be equal to true, false, or nil, it'll be equal to a string with length zero.
Disclaimer: the only thing I know about Lua is that I don't know anything about Lua.
It appears that Lua treats equality comparisons using == and comparisons done in control structures (if, while, for, etc.) differently.
According to the Lua 5.1 manual (section 2.4.4, Control Structures),
The condition expression of a control structure can return any value.
Both false and nil are considered false. All values different from nil
and false are considered true (in particular, the number 0 and the
empty string are also true).
It seems like this is consistent with what you are seeing. That is:
"" == false => false
"" == true => false
"" == nil => false
Because the comparison operator seems to be checking the type and the value.
However, if you use the variable in a conditional in a control structure, the behavior is slightly different. That is,
if "" then
print "Hello world!"
end
Will print Hello world!, because the empty string is different from both nil and false, and thus evaluates to a truthy value.
Related
There seems to be a difference between these two checks:
if not object then
if type(object) == "nil" then
However I really don't understand the difference.
if type is "nil", shouldn't a not object then also work?
Lua, like many other dynamically typed languages, has the concept of "truthy" and "falsy", where boolean expressions can handle more values than just actual booleans.
Each non-boolean value has a specific meaning attached when used in a boolean expression. Specifically:
nil and false are "falsy"
everything else is "truthy"
That is why (not nil) == (not false), but type(nil) ~= type(false), because not x is a boolean expression that coerces x to truthy/falsy, while type() checks the actual type.
I was doing some anti metamethod hooks and I was curious on what metamethod is called in the code below between the parentheses
local test = "random string"
if (test == "random string") then --// What metamethod if any is being called here?
print("equals")
end
I've done some research and took a look at the __eq metamethod, but that is only called when comparing two tables which isn't what I'm tryna do.
If there isn't any metamethod being called then how would I protect the if condition?
-- Update --
What if I put every string inside of a table for example:
local _Table1 = {"Test1", "Test2"}
local _Table2 = {"Test1", "Test2"}
for Index, Value in next, _Table1 do
if Value == _Table2[Index] then
print("Tables Match!")
elseif Value ~= _Table2[Index]
print("Tables Don't Match!")
end
end
I'm not doing any string converting here, but I'm showing what I could try and do for a simple anti tamper.
The only operator in the parenthesized expression is ==. Thus the only metamethod in question is __eq. The Lua Reference Manual states the following on __eq:
__eq: the equal (==) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are either both tables or both full userdata and they are not primitively equal.
Your values are strings and thus no metamethod will be called - even if you were to modify the string metatable to alter __eq.
Strings in Lua are always interned, so this comparison will always run in constant time. Since it is a primitive comparison, it can't possibly throw an error. No metamethod is called.
There is nothing to protect from: No possible performance issue / DoS vulnerability, no possible fancy side effects or code execution, no possible error.
(Highly theoretically: If a debug hook running every n instructions is registered, it might fire as the comparison is executed. You can hardly "protect" against a debug hook though.)
But it makes sense, for example a check against the Length.
A check against the Content seems also possible but need more lines.
And i like one liner in Lua Standalone to show...
> _VERSION
Lua 5.4
> eqtab = setmetatable({"Test1", "Test2"}, {__eq = function(left, right) print('SIMON SAYS:') return(#left == #right) end})
> eqtab == {1}
SIMON SAYS:
false
> eqtab == {}
SIMON SAYS:
false
> eqtab == {"Test1", "Test2"}
SIMON SAYS:
true
> eqtab == {1, 2}
SIMON SAYS:
true
I'm just learning lua, and see these two ways to check for nil
local stats = game.ServerStorage.PlayerMoney:FindFirstChild(player.Name)
if (stats ~= nil) then
-- do stuff
end
if (stats) then
-- do stuff
end
Are the if statements equivalent? If so, is there any advantage to including the extra "~= nil" part?
Statement "~= nil" works also if stats = false.
You can read in docs:
The condition expression of a control structure can return any value.
Both false and nil are considered false. All values different from nil
and false are considered true (in particular, the number 0 and the
empty string are also true).
What does this block of code do?
local name = value or 0
Please tell me that it makes it zero if nil and makes it value if not nil.
Short answer
yes
Looooong answer
You're right. While in other languages, the logical operators return either true or false, Lua (and some other languages) does something more clever:
When the first parameter of or is truthy, it evaluates to that value, if it's not, it evaluates to the second one. And does it the other way around: if its left-hand-side is falsey, it evaluates to that, otherwise it evaluates to its RHS.
Logically, this means that or evaluates to truthy if either operand is truthy and and evaluates to falsey if either of its operands is.
This is often used as an equivalent of
if value then
name = value
else
name = 0
end
And it effectively does the same. It is also often use to assign default values to variables like this:
function call(name)
name = name or "you"
print("Hey "..name.."! Come here for a moment!")
end
Note though, that this doesn't work
function alarm(real)
real = real or true
print "ALAAARM!"
if real then print "This is NOT a drill!" end
end
alarm(false)
This will always print "ALAAARM!" "This is NOT a drill!", because false is evaluated as falsey, so the or statement evaluates to its RHS, which is true. In this particular example, you would have to check explicitly if the argument is nil.
-- ...
real = (real == nil) and true or real
-- ...
This would work as intended, because only if real == nil, the and statement evaluates to true, and the or thus evaluates to its LHS. If real == nil is false, then the and evaluates to that, thus the or statement evaluates to its RHS (because its LHS is false).
It's also worth mentioning that both and and or are short-circuited. What this means is:
function foo(bar)
print(bar)
return bar
end
io.write "First: "
local A = foo(nil) or foo(false)
io.write "Second: "
local B = foo(true) or foo(true)
This will print "First: nil false" on the first two lines, but then "Second: true" on the third line. The last call to foo is not even executed, because at that point the or statement already knows it's going to return its left operand.
I have used repl.it to see what it returned, just for the sake of curiosity, and it turned out that
not nil
returnes true
Why is it? Is it because in Lua everything should be rather true or false in the end?
Repl.it link: https://repl.it/repls/SanePastelHarrier
Because nil is false when converted to boolean:
2.2 Booleans
The boolean type has two values, false and true, which represent the traditional boolean values. However, booleans do not
hold a monopoly of condition values: in Lua, any value may represent a
condition. Conditionals (such as the ones in control structures)
consider both false and nil as false and anything else as true.
Beware that, unlike some other scripting languages, Lua considers both zero
and the empty string as true in conditional tests.
And not treats its argument as a boolean:
3.3 Logical Operators
The logical operators areand, or, and not. Like control structures, all logical operators consider both false and nil
as false, and anything else as true.