What is local name = value or 0 in lua? - 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.

Related

Lua nonsense to find if something is nil

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.

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

nil check, best way?

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

Is there a null value in maxima?

I have the following two functions:
find(list, closure) := block(
filter: sublist(list, closure),
if length(filter) > 0 then filter[1] else null)$
find_index(list, closure) := block(
filter: sublist_indices(list, closure),
if length(filter) > 0 then filter[1] else null)$
In other languages I would return null or nil here, if the element that is searched can't be found. But I think this keyword doesn't exist in maxima. What is the common convention in maxima for what to return in this case? Maybe false?
false is indeed the most commonly used value to represent "not there". It is not required, but there is a pretty consistent convention for it.
Note that if foo then bar evaluates to false if foo evaluates to false. Therefore if foo then bar else false is equivalent to if foo then bar, which is a little shorter.
From the manual:
-- Constant: false
'false' represents the Boolean constant of the same name. Maxima
implements 'false' by the value 'NIL' in Lisp.
So the lisp equivalent of an empty result is false.

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.

Resources