If Statements in Lua - if-statement

In all other programming languages I've encountered, if statements always require a boolean to work, however in Lua the following code does not contain any errors. What is being checked in this if statement if both true and false statements can't be made? How can you only check "if (variable) then"? I am new to programming and currently working with Roblox Studio, any help would be very appreciated.
function onTouched(Obj)
local h = Obj.Parent:FindFirstChild("Humanoid")
if h then
h.Health = 0
end
end
script.Parent.Touched:Connect(onTouched)

Most languages have their own rules for how values are interpreted in if statements.
In Lua, false and nil are treated as false. All other values are treated as true.

if h == nil (null)
So if it couldn't find a humanoid in the object that touched the script's parent, it will be false (null), otherwise true (not null).
So
if [ObjectName] then
equals to if [ObjectName] != null then
*Only valid for objects (non primitive values)
It's like that in script languages.

if h then end
is basically equivalent to
if h ~= nil and h ~= false then end
In Lua all values that are not nil or false are considered to be logically true.
if h then end is usually used to check wether h is not nil. So if code depends on wether h has been defined you put it in a condition like that.
In your example h is being index. indexing nil values is not allowed. So befor you index it you should make sure it isn't nil to avoid errors.
Checking return values of functions is good practice.

Related

Check if all elements of list are prime in Raku

my #g = (1,2,3,4);
say reduce {is-prime}, #g; # ==> gives error
say reduce {is-prime *}, #g; #==> gives error
say reduce {is-prime}, (1,2,3,4); # ==> gives error
say so is-prime #g.all; # ==> gives error
How to check if all elements of list are prime in Raku?
The answers above are all helpful, but they fail to explain why your solution does not work. Basically reduce is not going to apply a function (in your case, is-prime) to every member of a list. You want map for that. The error says
Calling is-prime() will never work with signature of the proto ($, *%)
Because reduce expects an infix, thus binary, function, or a function with two arguments; what it does is to apply them to the first pair of elements, then to the result and the third element, and so on. Last statement does not work for a similar reason: you are calling is-prime with a list argument, not a single argument.
You're basically asking: are there any elements in this list which are not prime? I would write that as:
say "not all prime" if #g.first: !*.is-prime;
Please note though, that apparently 1 is not considered prime according to the is-prime function:
say 1.is-prime; # False
so the first would trigger on the 1 in your example, not on the 4.
There are of course may ways to do this. A very explicit way is using a for loop:
for #g -> $g {
if $g.is-prime {
say $g;
}
}
Or with a grep (you could leave the $_ implicit):
#g.grep({ $_.is-prime }).say
Both above are assuming you really want to filter the primes out. Of course you can also really check each number and get a boolean:
#g.map({ .is-prime }).say
There is a big problem with this:
say reduce {is-prime}, #g;
You created a lambda:
{ }
The only thing it does is calls a function:
is-prime
You didn't give the function any arguments though.
Is it just supposed to guess what the arguments should be?
If you meant to pass in is-prime as a reference, you should have used &is-prime rather than {is-prime}.
Of course that still wouldn't have worked.
The other problem is that reduce operates by recursively combining values.
It can't do that if it operates on one argument at a time.
The bare block lambda {}, takes zero or one argument, not two or more.
reduce is often combined with map.
It happens so often that there is a Wikipedia page about MapReduce.
say ( map &is-prime, #g ==> reduce { $^a and $^b } );
# False
say ( map &is-prime, 2,3,5 ==> reduce { $^a and $^b } );
# True
I wrote it that way so that map would be in the line before reduce, but perhaps it would be more clear this way:
say reduce {$^a and $^b}, map &is-prime, 2,3,5;
# True
reduce with an infix operator is so common that there is a shorter way to write it.
say [and] map &is-prime, 2,3,5;
# True
Of course it would be better to just find the first value that isn't prime, and say the inverse.
Since if there is even a single value that isn't prime that would mean they can't all be primes.
You have to be careful though, as you may think something like this would always work:
not #g.first: !*.is-prime;
It does happen to work for the values you gave it, but may not always.
first returns Nil if it can't find the value.
not (2,3,5).first: !*.is-prime;
# not Nil === True
not (2,3,4).first: !*.is-prime;
# not 4 === False
not (2,3,0,4).first: !*.is-prime;
# not 0 === True
That last one returned 0 which when combined with not returns True.
You could fix this with defined.
not defined (2,3,0,4).first: !*.is-prime;
# False
This only works if first wouldn't return an undefined element that happens to be in the list.
(Int,Any).first: Real
# Int
defined (Int,Any).first: Real
# False
You could fix that by asking for the index instead of the value.
You of course still need defined.
(Int,Any).first: :k, Real
# 0
defined (Int,Any).first: :k, Real
# True
The other way to fix it is to just use grep.
not (2,3,0,4).grep: !*.is-prime;
# not (0,4) === False
Since grep always returns a List, you don't have to worry about checking for 0 or undefined elements.
(A List is True if it contains any elements, no matter what the values.)
grep is smart enough to know that if you coerce to Bool that it can stop upon finding the first value.
So it short-circuits the same as if you had used first.
This results in some fairly funky code, with those two negating operators. So it should be put into a function.
sub all-prime ( +#_ ) {
# return False if we find any non-prime
not #_.grep: !*.is-prime
# grep short-circuits in Bool context, so this will stop early
}
This could still fail if you give it something weird
all-prime 2,3,5, Date.today;
# ERROR: No such method 'is-prime' for invocant of type 'Date'
If you care, add some error handling.
sub all-prime ( +#_ ) {
# return Nil if there was an error
CATCH { default { return Nil }}
# return False if we find any non-prime
not #_.grep: !*.is-prime
}
all-prime 2,3,5, Date.today;
# Nil
use the all junction:
say so all #g».is-prime; # False

Test answer of the boolean 'true' explaination

Im very confused why the first 3 arnt all correct. As isn't true a keyword, it of course is a Boolean literal and is interchangeable with 1?
True and False are not keywords, they are boolean values because they are associated with 1 and 0 respectively. For a complete list of keywords see Is it possible to get a list of keywords in Python?

Python 2.7 Boolean Operators Logic

I am currently in the course of learning Python 2.7 and have come across the Equality and Boolean operators
My question is:
Why False and 1 is False but True and 1 is 1
Likewise, False or 1 is 1 but True or 1 is True
Can someone kindly explain why this is happening
Many thanks
and returns the first 'falsy' (False, zero, empty string or list, etc.) value it sees, or the final value if none were falsy. Further values are not even evaluated, since they can't change the result.
or likewise returns the first 'truthy' (True, non-zero, non-empty string or list, etc.) value it sees (or the final one if there were none), and doesn't evaluate the rest.
This behavior is sometimes more convenient than strictly returning only True or False.

improve my Haskell code of all function

I am trying to implement all function in Haskell, it works fine but I think my base case is not good , if I set the result of the base case to False it makes more sense, I mean not of the members of an empty list passes the test condition in real word so answer should be false but on the other hand if I define it to false the whole function does not work properly .
all' test [] = True
all' test (x:xs)
| not (test x) = False
| otherwise = all' test xs
Consider this: for an empty list the predicate holds for all elements in the list.
Why? Because there are no elements that violate it.
Therefore the base case of the empty list is True.
all is intended to have the same meaning as the statement in formal logic, ∀xϵL: test(x) where L is the list that is the first argument. If you aren't familiar with formal logic, the important thing to understand is that this statement "returns" true even for an empty list. This is called vacuous truth (see http://en.wikipedia.org/wiki/Vacuously_true if you are curious).
The fact that returning true on an empty list makes all' easier to implement is a good example of why vacuous truth is a good idea, but if you want to implement it to return False for an empty list all you have to do is add one more case.
all' _ [] = False --here I have changed test to _ since we don't care what it is
all' test x:[] = test x --the new case
all' test (x:xs)
| not (test x) = False
| otherwise = all' test xs
You can also implement this using a fold, like so:
all' test = foldr (&&) True . map test
You can basically imagine this as applying "and" (&&) to every pair of booleans, with the first one being True. If the first one was False, all would return False regardless of the input due to the nature of && (anything anded with False is False.)
For more details of how folds work, see Learn You a Haskell and scroll to "Only folds and horses".

Cond If And Or in Racket

Can someone please explain these functions for me in racket. I`m totally lost. Please help me with some examples. Thanks! I just cannot figure these functions out for the life of me.
First, the If:
(if (positive? 1) 1 -1)
Racket first evaluates if 1 is positive (which is the first expresion (positive? 1)). If it is, returns 1, else, return -1. This is equivalent to c-like languages doing:
if ( positive?(1))
return 1
else
return -1
The Cond is basically a if that has multiple options. The equivalent in C-like languages would be else-if
(cond [(first-condition) (what-to-do)]
[(second-condition) (what-to-do)]
[(third-condition) (you-get-the-idea)])
And and Or are just the logical operators, equivalent to && and || in C-like languages
(and true true) => true
(and true false) => false
(or true true) => true
(or true false) => true
(or false false) => false
If is the turnary operator. It has three arguments, unless the first argument has a value of #f it will return the value of the second argument, otherwise the value of the third argument.
OR accepts one or more arguments, evaluates them one at a time left to right, and returns the first value if finds that is not #f, and returns #f if no argument satisfies that condition.
AND accepts one or more arguments evaluate them one at a time left to right, if it finds one that is #f it returns #f, otherwise it returns the value of the last argument that it evaluates.
COND accepts one or more arguments, each with one or more sub arguments (2 is the usual number though). It evaluates each argument left to right one at a time by evaluating the first subargument. If it is not #f then it evaluates each of the rest of the sub-arguments (if any) in order and returns the value of the last argument. Otherwise it moves onto the next argument and evaluates it the same way. else is a special sytax within these sub-arguments that is always treated as if it is not #f.
And here argument is understood to mean any valid s-expression.
NB: If you are familiar with non-lisp languages this is the answer for you. I'm not trying to explain them in other way than other code. Other answers do however so this is just a supplement.
None of those are functions, but special forms.
(if predicate
consequent
alternative)
is pretty much like Algol-dialects if
if( predicate )
{
consequent
}
else
{
alternative
}
Note that predicate, consequent and alternative can be anything from a complex expression to a simple value.
cond works more like an if, elseif..., else:
(cond (predicate1 consequent1)
(predicaten consequentn)
(else alternative))
and works like && in algol dialects. Thus false && print("Do it!") doesn't print anything since it short circuits.
(and #f (display "Do it!")) ; ==> #f (and does not display anything since first term was false)
(and 1 2 3) ; ==> 3 (3 is the last true value. In Scheme everything except #f is true.)
or works like || in algol dialects. thus true || print("Do it!") doesn't print since first term was true.
(or 'mama (display "Do it")) ; ==> mama (first true value, does not print "do it")