nil check, best way? - lua

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).

Related

What lua metamethod is being called here?

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

What is local name = value or 0 in lua?

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.

Why does "not nil" return true in Lua?

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.

Test variable for Numeric in one line

I found this code on another thread.
def is_number? string
true if Float(string) rescue false
end
Instead of using a method to return true or false, I'd like to do this "is_numeric" test in one line, in an if statement. Can someone explain if this is possible? I'm getting errors at the moment both when the string variable is null and when it contains non-numeric characters.
if Float(string)
* do something
else
* do something else
end
if Float() is pointless code, since Float() will either return a truthy value or raise an error (based on my limited look at the source code - as of writing, you can follow the code path from line #2942). I'd suggest you're asking the wrong question/looking at the problem wrong (it'd be helpful to know what you're actually trying to achieve).
To do something with Float() on one line and avoid breaking code, use rescue as a statement modifier, as has been done in the is_number? method posted.
Float(string) rescue 0.0 # trying to emulate String#to_f!
Ensuring the phone number is 10 digits, numbers only, is quite simple.
PHONE_NUM_LENGTH = 10
string.length == PHONE_NUM_LENGTH && string.count('0-9') == PHONE_NUM_LENGTH
will return the true/false value representing this check. This is more efficient than a Regex.
The first part,
string.length == PHONE_NUM_LENGTH
checks whether the string is 10 characters long. The second,
string.count('0-9') == PHONE_NUM_LENGTH
checks whether it has exactly 10 numeric characters.

evaluating variable and assigning to another variable in one line

I have a variable that's returned from the db as a string. I convert it to a number and then test like so:
if tonumber(v.active) == 1 then
elements.active.value = true
else
elements.active.value = false
end
The value in elements.active.value is being used to diplay a checkbox. I'm wondering if there's a way to combine this all into one statement?
EDIT 1
I'm using a lua boolean value to set the checkbox, so I can't use 1. You have to use true / false.
I'm not so much interested in whether or not I can use 1 or true to set the value. I'm more interested in keeping the logic the same, but simplifying.
What I was really after was something like what you can do in php like so:
max = array_key_exists ('max', $options) ? $options['max'] : 0;
it'll use either the $options['max'] value or 0 depending on the eval.
Like this:
elements.active.value = tonumber(v.active) == 1
Because the result of a relational operator like == is boolean, just what you assigned to elements.active.value in your piece of code.
Lua reference manual: Relational Operators
The relational operators in Lua are
== ~= < > <= >=
These operators always result in false or true.

Resources