When should comparator === be used over ==? - if-statement

So I've been actively programming bot in school and work the past 5 years, but I never tried to find out the difference between == and ===.
I can see the difference of a comparator using a single =, it'll look at the value of the left handed variable through the loop, ex:
while($line = getrow(something))
So what's the difference between == and === in statements such as:
if ($var1 === $var2)
//versus
if ($var1 == $var2)
Likewise:
if ($var1 !== $var2)
//versus
if ($var1 != $var2)
I have always used double equals, I have never used tripple.
The languages I use are :php, vb.net, java, javascript, c/c++.
I'm interested in learning systematically what is going on in a tripple quote that is different than that of a double quote.
When should one be used over another? Thanks for appeasing to my curiosity :)

Typically, == looks at equality of value only. So, for instance...
5 == 5.0 //true
However, === also considers value and type (in the languages I am familiar with).
var five = 5;
var five_float = (float)5.0;
five === 5; //true - both int, both equal to 5
five_float === 5; //false - both equal 5 but one is an int and one is a float
FYI, the = operator (usually called the assignment operator) is used to set the value of the left side parameter to the right side. This is pretty obvious. However, in most languages, this will also return true if the assignment is successful. You want to avoid using = where you mean to use == (or ===) because it will look like a comparison, but it's not - and it will return true unexpectedly.
For instance, lets say you want to check if a number is equal to 10...
myNumber = 7;
if(myNumber = 10)
{
//will always be true and execute this code because myNumber will successfully
//be assigned the value of 10 instead of checking to see if the number is 10.
//oops!
}
A final note - this is true in PHP and JavaScript. I don't think there is a === operator in C++ or Java and == has a slightly different meaning as well.

$a === $b TRUE if $a is equal to $b, and they are of the same type. (introduced in PHP 4)
$a !== $b TRUE if $a is not equal to $b, or they are not of the same type. (introduced in PHP 4)
Reference

== will check the value only (equality operator), where === checks the data type as well (strict equality operator).
1 == '1' is true.
1 === '1' is false - the first is an Integer, the second is a String.
1 == true is true.
1 === true is false - the first is an Integer, the second is a Boolean.
Generally you want to use == (equality operator) but sometimes you want to make sure things are of certain types. I'm sure someone can provide an example, I can't think of one off the top of my head, but I've definitely used it.

In PHP and JavaScript (I'm not sure of other languages where the triple === syntax is valid) the difference is that === is a strict comparison. While == is loose. That means that === compares value and type, but == just compares value. A perfect example of this is the buggy PHP code below:
$str = 'Zebraman stole my child\'s pet lime!';
// Search for zebra man
if(strpos($str, 'Zebraman')){
echo 'The string contains "Zebraman"';
}else{
echo 'The string doesn\'t contain "Zebraman"';
}
Example Here
Since strpos($str, 'Zebraman') returns 0 (The index of the string Zebraman), and since 0 is falsy. That code will output The string doesn't contain "Zebraman". The correct code uses a strict comparison with false:
$str = 'Zebraman stole my child\'s pet lime!';
// Search for zebra man
if(strpos($str, 'Zebraman') !== false){
echo 'The string contains "Zebraman"';
}else{
echo 'The string doesn\'t contain "Zebraman"';
}
Example Here
See the PHP man page on strpos

I don't know if this holds true for all languages but in javascript the === stands for type comparison.
0 == false (true) 0 === false (false)
It is a common js error to not use the === when comparing a falsy value.
var a;
if(a) do something
(if a is zero the if will not get entered)

Related

Cannot Combine Conditions Normally in If Statement in VBScript

I'm trying to determine if it's between the hours of 12 am and 1 am. Here is my if statement:
If InStr(Time,"12") AND InStr(Time,"AM") Then
' Do something
Else
' Do something else
End If
The problem is that this statement evaluates to false, even if both of the conditions are true. I know this because I have tried a nested if like this
If InStr(Time,"12") Then
If InStr(Time,"AM") Then
' Do something
...
And that works. This also works
If InStr(Time,"12")<>0 AND InStr(Time,"AM")<>0 Then
' Do something
...
But if it works as a nested if, why can't I test both of the nested if conditions in a single if statement?
I replaced the InStr function calls with the values that they return
If 1 AND 10 Then
' Do something
Else
' Do something else
End If
And the same thing happened: the if statement evaluated as false and the "Do something else" commands were executed instead. But when I nested the second condition as another if statement inside the first if statement, the "Do something" commands were executed.
Why is that and is there any way to do this without the <>0 and without nesting?
If Time() >= TimeValue("12:00:00") AND Time() <= TimeValue("23:59:59") then
'Do Something
ElseIf Time() >= TimeValue("00:00:00") AND Time() <= TimeValue("01:00:00") then
'Do the same
Else
'Do something different
End If
This should work :)
The problem you observed is caused by the fact that VBScript uses the same operators for boolean and bit operations, depending on the data type of the operands. The InStr function returns a numeric value unless one of the strings is Null, so the operation becomes a bitwise comparison instead of a boolean comparison, as JosefZ pointed out. The behavior is documented:
The And operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in result [...]
Demonstration:
>>> WScript.Echo "" & (True And True)
True
>>> WScript.Echo "" & (6 And 1) '0b0110 && 0b0001 ⇒ 0b0000
0
>>> WScript.Echo "" & (6 And 2) '0b0110 && 0b0010 ⇒ 0b0010
2
To enforce a boolean comparison you need to use InStr(...) > 0 or CBool(InStr(...)) (both of which evaluate to a boolean result) instead of just InStr(...) (which evaluates to a numeric result).
Date and Time are stored as number of days, where midnight is 0.0, and 1 am is 1/24 :
If Time <= 1/24 Then ' or If Time <= #1am# Then
When you using Time() function and if result like that 10:12:12 AM in this way Instr will result Ture because Instr by default use vbbinarycompare looking For any 12in binary format in 10:12:12 AM and there is sec and min 12 so it will Return True .
just try this :
myHour=replace(Time,Right(Time,9),"") 'get only the hour from time
myAMPM=replace(Time,Time,Right(Time,2)) 'get only AM or PM from time
If InStr(1,myHour,12,1) > 0 AND InStr(1,myAMPM,"AM",1) > 0 Then
wscript.echo "True"
Else
wscript.echo "False"
End If

Else/If statement help in swift

I'm getting an error when I try to use an if/else statement in Xcode 6 with Swift. This is what I have
} else if countElements(sender.text) == 1, 2
It's telling me:
Type 'String!' does not conform to protocol '_CollectionType'
How can I compare two values on one line?
You can use "||" = "or"
} else if countElements(sender.text) == 1 || countElements(sender.text) == 2 {
}
The other answer correctly shows the way to make 2 comparisons in Swift, but this can be done in a single statement thanks to Swift's pattern matching operator. For example:
if 1...2 ~= countElements(sender.text) {
println("count is 1 or 2")
}
Basically, the provided statement is true if the number of characters in your string is inclusively between 1 and 2.
You can also use the contains global function, providing it a range and the element to check for inclusion:
contains(1...2, countElements(sender.text))

How to do a single line If statement in VBScript for Classic-ASP?

The "single line if statement" exists in C# and VB.NET as in many other programming and script languages in the following format
lunchLocation = (dayOfTheWeek == "Tuesday") ? "Fuddruckers" : "Food Court";
does anyone know if there is even in VBScript and what's the extact syntax?
The conditional ternary operator doesn't exist out of the box, but it's pretty easy to create your own version in VBScript:
Function IIf(bClause, sTrue, sFalse)
If CBool(bClause) Then
IIf = sTrue
Else
IIf = sFalse
End If
End Function
You can then use this, as per your example:
lunchLocation = IIf(dayOfTheWeek = "Tuesday", "Fuddruckers", "Food Court")
The advantage of this over using a single line If/Then/Else is that it can be directly concatenated with other strings. Using If/Then/Else on a single line must be the only statement on that line.
There is no error checking on this, and the function expects a well formed expression that can be evaluated to a boolean passed in as the clause. For a more complicated and comprehensive answer see below. Hopefully this simple response neatly demonstrates the logic behind the answer though.
It's also worth noting that unlike a real ternary operator, both the sTrue and sFalse parameters will be evaluated regardless of the value of bClause. This is fine if you use it with strings as in the question, but be very careful if you pass in functions as the second and third parameters!
VBScript does not have any ternary operator.
A close solution in a single line and without using a user defined function, pure VBScript:
If dayOfTheWeek = "Tuesday" Then lunchLocation = "Fuddruckers" Else lunchLocation = "Food Court"
BTW, you can use JScript in Classic ASP if ternary opertor is so important to you.
edited 2017/01/28 to adapt to some of the non boolean condition arguments
Note: If all you need is to select an string based on an boolean value, please, use the code in the Polinominal's answer. It is simpler and faster than the code in this answer.
For a simple but more "flexible" solution, this code (the original code in this answer) should handle the usual basic scenarios
Function IIf( Expression, TruePart, FalsePart)
Dim bExpression
bExpression = False
On Error Resume Next
bExpression = CBool( Expression )
On Error Goto 0
If bExpression Then
If IsObject(TruePart) Then
Set IIf = TruePart
Else
IIf = TruePart
End If
Else
If IsObject(FalsePart) Then
Set IIf = FalsePart
Else
IIf = FalsePart
End If
End If
End Function
If uses the Cbool function to try to convert the passed Expression argument to a boolean, and accepts any type of value in the TrueValue and FalseValue arguments. For general usage this is fast, safe and fully complies to documented VBScript behaviour.
The only "problem" with this code is that the behaviour of the CBool is not fully "intuitive" for some data types, at least for those of us that constantly change between vbscript and javascript. While numeric values are coherent (a 0 is a False and any other numeric value is a True), non numeric types generate a runtime error (in previous code handled as false), except if it is a string with numeric content or that can be interpreted as true or false value in english or in the OS locale.
If you need it, a VBScript version "equivalent" to the ? javascript ternary operator is
Function IIf( Expression, TruePart, FalsePart )
Dim vType, bExpression
vType = VarType( Expression )
Select Case vType
Case vbBoolean : bExpression = Expression
Case vbString : bExpression = Len( Expression ) > 0
Case vbEmpty, vbNull, vbError : bExpression = False
Case vbObject : bExpression = Not (Expression Is Nothing)
Case vbDate, vbDataObject : bExpression = True
Case Else
If vType > 8192 Then
bExpression = True
Else
bExpression = False
On Error Resume Next
bExpression = CBool( Expression )
On Error Goto 0
End If
End Select
If bExpression Then
If IsObject( TruePart ) Then
Set IIf = TruePart
Else
IIf = TruePart
End If
Else
If IsObject( FalsePart ) Then
Set IIf = FalsePart
Else
IIf = FalsePart
End If
End If
End Function
BUT independently of the version used, be careful, you are calling a function, not using a ternary operator. Any code, or function call you put in TruePart of FalsePart WILL BE EXECUTED independently of the value of the condition. So this code
value = IIf( 2 > 3 , DoSomething(), DontDoSomething() )
WILL EXECUTE the two functions. Only the correct value will be returned to value var.
There's a weird trick possible (hi, Python!) for exact one-liner:
lunchLocation = array("Food Court", "Fuddruckers")(-(dayOfTheWeek = "Tuesday"))
The "magic" works because of a boolean operation specifics in VBScript.
True is actually -1 and False is 0, therefore we can use it as an index for array (just get rid of a minus). Then the first item of array will be a value for False condition and second item for True.
related to #MC_ND answer:
to execute only one function, you can do something like that:
If VarType(TruePart) = vbString and InStr(1,TruePart,"function:") = 1 then
IIf = GetRef(Mid(TruePart,10))()
Else
IIf = TruePart
End If
the same for the FalsePart, and call IIf() it like that:
value = IIf( 2 > 3 , "function:DoSomething", "function:DontDoSomething" )
and will call DoSomething() or DontDoSomething()

How to accept numbers and specific words?

i have validating a clothes size field, and want it to accept only numbers and specific "words" like S, M, XL, XXL etc. But i am unsure how to add the words to the pattern. For example, i want it to match something like "2, 5, 23, S, XXXL" which are valid sizes, but not random combinations of letters like "2X3, SLX"
Ok since people are not suggesting regexp solutions i guess i should say that this is part of a larger method of validation which uses regexp. For convenience and code consistency i want to do this with regexp.
Thanks
If they're a known set of values, I am not sure a regex is the best way to do it. But here is one regex that is basically a brute-force match of your values, each with a \b (word boundary) anchor
\b2\b|\b5\b|\b23\b|\bXXXL\b|\bXL\b|\bM\b|\bS\b
Sorry for not giving you a straight answer. regexp might be overkill in your case. A solution without it could, depending on your needs, be more maintainable.
I don't know which language you use so I will just pick one randomly. You could treat it as a piece of pseudo code.
In PHP:
function isValidSize($size) {
$validSizeTags = array("S", "M", "XL", "XXL");
$minimumSize = 2;
$maximumSize = 23;
if(ctype_digit(strval($size))) { // explanation for not using is_numeric/is_int below
if($size >= $minimumSize && $size <= $maxiumSize) {
return true;
}
} else if(in_array($size, $validSizeTags)) {
return true;
} else {
return false;
}
}
$size = "XS";
$isValid = isValidSize($size); // true
$size = 23;
$isValid = isValidSize($size); // true
$size = "23";
$isValid = isValidSize($size); // true, is_int would return false here
$size = 50;
$isValid = isValidSize($size); // false
$size = 15.5;
$isValid = isValidSize($size); // false, is_numeric would return true here
$size = "diadjsa";
$isValid = isValidSize($size); // false
(The reason for using ctype_digit(strval($size)) instead of is_int or is_numeric is that the first one will only return true for real integers, not strings like "15". And the second one will return true for all numeric values not just integers. ctype_digit will however return true for strings containing numeric characters, but return false for integers. So we convert the value to a string using strval before sending it to ctype_digits. Welcome to the world of PHP.)
With this logic in place you can easily inject validSizeTags, maximumSize and minimumSize from a configuration file or a database where you store all valid sizes for this specific product. That would get much messier using regular expressions.
Here is an example in JavaScript:
var patt = /^(?:\d{1,2}|X{0,3}[SML])$/i;
patt.test("2"); // true
patt.test("23"); // true
patt.test("XXXL"); // true
patt.test("S"); // true
patt.test("SLX"); // false
Use Array Membership Instead of Regular Expressions
Some problems are easier to deal with by using a different approach to representing your data. While regular expressions can be powerful, you might be better off with an array membership test if you are primarily interested in well-defined fixed values. For example, using Ruby:
sizes = %w[2 5 23 S XXXL].map(&:upcase)
size = 'XXXL'
sizes.include? size.to_s.upcase # => true
size = 'XL'
sizes.include? size.to_s.upcase # => false
seeing as it is being harder than i had thought, i am thinking to store the individual matched values in an array and match those individually against accepted values. i will use something like
[0-9]+|s|m|l|xl|xxl
and store the matches in the array
then i will check each array element against [0-9]+ and s|m|l|xl|xxl and if it matches any of these, it's valid. maybe there is a better way but i can't dwell on this for too long
thanks for your help
This will accept the alternatives one or more times, separated by whitespace or punctuation. It should be easy enough to expand the separator character class if you think you need to.
^([Xx]{0,3}[SsMmLl]|[0-9]+)([ ,:;-]+([Xx]{0,3}[SsMmLl]))*$
If you can interpolate the accepted pattern into a string before using it as a regex, you can reduce the code duplication.
This is a regular egrep pattern. Regex dialects differ between languages, so you might need to tweak something in order to adapt it to your language of choice (PHP? It's good form to include this information in the question).

How to disallow non-alphanumeric characters in ColdFusion using a RegEx

I am using ColdFusion 9.0.1.
I am trying to test whether a user has provided a non alphanumeric value. If they have, I want to return false. I'm pretty sure I am close, but I keep getting an error:
Complex object types cannot be converted to simple values.
I've tried multiple ways of making this work, but I can't get it to work.
Specifically, I want to allow only a through z and 0 through 9. No spaces, or special characters.
Can you help me tweak this?
<cfscript>
LOCAL.Description = trim(left(ARGUMENTS.Description, 15));
if (len(LOCAL.Description) lte 4) {
return false;
} else if (reMatchNoCase("[^A-Za-z0-9_]", LOCAL.Description) neq "") {
return false;
} else {
return true;
</cfscript>
W
reMatchNoCase returns Array which cannot be compared to the string, use ArrayLen() on the result in order to find out if there any matches
There is actually another problem in your code. First line will produce an error if the length of the description is less than 15, which means that the first IF is obsolete since it will always be false.
reMatchNoCase("[^A-Za-z0-9_]", LOCAL.Description) neq ""
It is because ReMatchNoCase returns an array, not a simple string. Either check the array length, or better yet, use ReFindNoCase instead. It returns the position of the first match, or 0 if it was not found.
You can also try the following approach:
<cfscript>
local.description = trim(local.description);
return reFind("(?i)^[A-Z0-9_]{5,}$", local.description)?true:false;
</cfscript>
I'm late to the party but reFindNoCase is the optimal solution in 2021. Here's how I would handle the code in the original question:
// best practice not to have a local var name identical to an argument var
var myValue = trim( left( arguments.description, 15 ) );
// return false if myValue is less than 4 or has special characters
return(
!len( myValue ) lte 4 &&
!reFindNoCase( "[^a-z0-9]", myValue )
);