Assigning to multiple variables fails for even number of variables [duplicate] - vb6

Working with legacy code I came across some strange variable assignments that I am not sure are legal VB6 syntax, but I cannot find the documentation to back up the feeling.
Dim ComStart, ComEnd, CR As Boolean
ComStart = ComEnd = CR = False
My suspicions are
a) the original declarations should be
Dim ComStart as Boolean, ComEnd as Boolean, CR as Boolean
b) the declarations as they are implemented now will not assign anything to ComStart.
Any answers or documentation are much appreciated

The code you have found is technically legal VB6, because it compiles and runs. But it is very likely that the original author thought the code would do something different! There are two misunderstandings.
ComStart and ComEnd and CR are variants, not Booleans.
In VB6 = is the equality operator, not the assignment operator found in C.
CR = False does not change the value of CR. It compares the current value of CR to False, and evaluates as True if CR is equal to False. Let's say it evaluates as False
Now you have the expression ComEnd = False. Again, this does not change the value of ComEnd. It compares it with False, and evaluates as True if ComEnd is equal to False. This time let's say it evaluates as True.
Now you have the assignment statement ComStart = True. This sets the value of ComStart to True
So your original code
Dim ComStart, ComEnd, CR As Boolean
ComStart = ComEnd = CR = False
Creates two variants ComStart and ComEnd and a Boolean CR, and then
CR keeps its default value, False
ComEnd keeps its default value, Empty
ComStart is set to False because Empty = (Empty = False) is False.
Simple! ... I hope the rest of the legacy code is less, well, accidental.

So the code should be, as you guessed:
Dim ComStart as Boolean, ComEnd as Boolean, CR as Boolean
That's a common mistake on VB6 developers with little or no experience, or .NET developers working on VB6 code :). It works, because VB6 would assume the value assigned and would cast it automatically, but it can also cause nasty bugs really hard to debug.

Related

How to check if a value of an array is empty

I am writing a chess program and has to see whether certain value are empty. I tried
aPiece is an array of CommandButtons. cmdSquare is a control array of shapes.
Private aPiece(63) As CommandButton
...
For p = 0 To 63
If IsEmpty(aPiece(p)) Then
aPiece(p).Left = cmdSquare(p).Left
aPiece(p).Top = cmdSquare(p).Top
End If
Next p
All variable are declared and is seem to be IsEmpty function which is not working.
The IsEmpty method only returns meaningful information for variants. Since the array contains objects, you need to check like this:
If aPiece(p) Is Nothing Then
However, this seems like only part of the answer. The above logic is saying "If there is no piece in my array then update it's location". That doesn't make sense to me and will generate an error. You also need to add Not like below:
For p = 0 To 1
If Not aPiece(p) Is Nothing Then
aPiece(p).Left = cmdSquare(p).Left
aPiece(p).Top = cmdSquare(p).Top
End If
Next p
It depends on the datatype of aPiece. If it is a variant and you haven't assigned a value to it, IsEmpty will return true. However, if it is a String, Date, Integer, etc. those are automatically initialized (String will be an empty string, Integer will be 0) so IsEmpty will return false.
A pretty good reference is this page: IsEmpty Function - Visual Basic 6.0

|| and && aren't methods on Object -- what are they?

The single pipe "or" | exists as a method on TrueClass and FalseClass, but the short circuit || operator does not. Neither does it exist as a method on Object.
This seems to be an exception to ruby's "everything is an object" metaphor.
Main Question: Syntactically speaking, what are || and &&? Are they just baked bits of global syntax?
Secondary Question: I'm flagging this as not part of the main question, because it is potentially subjective, though I suspect it probably isn't.
Is there a language design or performance reason for this asymmetry? It seems to me both operators could have been implemented as methods on Object. Something like:
class Object
def short_circuit_or(other)
!nil? ? true :
!other.nil? ? true : false
end
end
I assume there is a reason they were not. What is it?
Both | and || are operators. || is part of the language while | is implemented as a method by some classes (Array, FalseClass, Integer, NilClass and TrueClass) .
In programming languages, | is used in general as the bitwise OR operator. It combines the bits of its integer operands and produces a new integer value. When used with non-integer operands, some languages convert them to integer, others prohibit such usage.
|| is the logical OR operator. It combines two boolean values (true or false) and produces another boolean value. When its operands are not boolean values, they are converted to boolean by some languages. Ruby (and JavaScript and other languages) evaluate its first operand as boolean and the value of the expression is the value of its first operand if its boolean value is true or the value of its second operand if the logical value of its first one is false. The type of the resulting value is its original type, it is not converted to boolean.
Each language uses its own rules to decide what non-boolean values are converted to false (usually the number 0, the empty string '' and null or undefined); all the other values are converted to true. The only "false" values in Ruby are false (boolean) and nil (non-boolean); all the other values (including 0) are "true".
Because true || anything is true and false && anything is false, many programming languages including Ruby implement short-circuit evaluation for logical expressions.
Using short-circuit evaluation, a logical expression is evaluated from left to right, one operand at a time until the value of the expression can be computed without the need to compute the other operands. In the examples above, the value of anything doesn't change the value of the entire expression. Using short-circuit evaluation, the value of anything is not computed at all because it does not influence the value of the entire expression. Being anything a method call that takes considerable time to execute, the short-circuit evaluation avoids calling it and saves execution time.
As others already mentioned in comments to the question, implementing || as a method of some class is not possible. The value of its second operand must be evaluated in order to be passed as argument to the method and this breaks the short-circuiting behaviour.
The usual representation of the logical values in programming languages uses only one bit (and I guess Ruby does the same.) Results of | and || are the same for operands stored on one bit.
Ruby uses the | symbol to implement different flavors of the OR operation as follows:
bitwise OR for integers;
non-short-circuit logical OR for booleans and nil;
union for arrays.
An expression like:
x = false | a | b | c
ensures that all a, b and c expressions are evaluated (no short-circuit) and the value of x is the logical OR of the logical values of a, b and c.
If a, b and c are method calls, to achieve the same result using the logical OR operator (||) the code needs to look like this:
aa = a
bb = b
cc = c
x = aa || bb || cc
This way each method is called no matter what values are returned by the methods called before it.
For TrueClass, FalseClass and NilClass, the | operator is useful when short-circuit evaluation is not desired.
Also, for Array (an array is just an ordered set), the | operator implements union, an operation that is the semantically equivalent of logical OR for sets.

Integer and String comparison conflict in VBScript

The below VBScript code while trying to run in HP-UFT confused me because the first statement prints True instead of False (which does not seem logical), while the second one prints False (which seems logical)
Code:
print 40 = "40"
a = 40
b = "40"
print a = b
Output:
True
False
It's perfectly logical (cough), there is only one data type in VBScript and that is Variant. However VBScript can handle many different sub types of the Variant data type.
When you compare
40 = "40"
VBScript is implicitly converting the String sub type to an Integer sub type and comparing the result which is the same as performing the following explicit conversion;
40 = CInt("40")
If you already have your variants defined however VBScript only attempts to implicitly convert them if the execution context fits (when it fits is a bit hazy and in some cases a straight up bug - See Ref).
To avoid this use explicit conversions when necessary.
a = CInt(b)
Useful Links
A: VBScript implicit conversion in IF statement different from variable to literals?
MSDN Blog - Typing Hard Can Trip You Up (Eric Lippert)

vbscript Type mismatch error when calling function

I am running into the Type Mismatch error when I attempt to call a function I created.
Example:
Function DoThis(paramA, paramB, paramC)
If paramA = "Something" Then
DoThis = DoSomething
ElseIf paramA = "This" Then
DoThis = DoSomethingDifferent
Else
DoThis = DoThisOtherThing
End If
End Function
Dim result: result = DoThis(valueA, ValueB, ValueC)
Can anyone see what my mistake could be? Other functions are working correctly. I have double checked the spelling by actually copying and pasting the function name where I call it. I have verified that the function name is not used anywhere else, i.e., as a constant or something else.
Note that when debugging this the ValType for all arguments is vbString. Also I am never able to enter the function, so it is not like I am debugging the function, enter it and then get the type mismatch.
ty.
VBScript has only one data type called a Variant. A Variant is a special kind of data type that can contain different kinds of information, depending on how it is used. Because Variant is the only data type in VBScript, it is also the data type returned by all functions in VBScript.
There are some subtypes of data that a Variant can contain (e.g. Empty, Null, string, integer, object, array etc.) You can use some conversion functions to convert data from one subtype to another, if that conversion is not implicit in VBScript. Now, pay your attention to real, factual data subtype of True and vbTrue.
The True keyword (boolean literal) has a value (inner representation) equal to -1.
On the other hand, vbTrue is one of few built-in constants and, in despite of it's name, has a subtype of Integer! It's one of so-called Tristate Constants:
Constant Value Description
vbUseDefault -2 Use default from computer's regional settings.
vbTrue -1 True
vbFalse 0 False
I hope next code could make clear all above statements:
Wscript.Echo _
vbTrue, CStr( vbTrue), VarType( vbTrue), TypeName( vbTrue) , _
vbNewLine, True, CStr( True), VarType( True), TypeName( True)
However, used with If _condition_ Then ..., there are some particularities; in brief:
The Then part of the If ... statement conditionally executes groups of statements only when a single test If condition is not False, i.e. any non-zero number esteems to be true, not only -1. Therefore you are able to use whatever variable or expression (numeric or string) you choose as long as the result is numeric...
Summarizing: If _expr_ Then ... is the same as
If CBool(_expr_) Then ...
The reason why retval is retuning mismatch error because it has a numeric value and an alpha value and wsh does not like that.
A sure way to get a type mismatch error for the published code is to define DoSomething etc. as Subs (which seems probable, given the names).
I cannot explain why this was a problem, but today I reduced the function down to a simple boolean return value and I still got the type mismatch error.
So I then created a new function with the same parameters and such. When I changed the call to the new function the error goes away.
My original function with the simple boolean return:(MISMATCH ERROR)
Function IsInstalledCheck(valueToCheck, expectedValue, checkType)
IsInstalledCheck = vbFalse
End Function
My new function with the a simple return:(Works)
Function IsItemInstalled(valueToCheck, expectedValue, checkType)
IsItemInstalled = vbFalse
End Function
EDIT
Note that I had tried this with the standard True / False values as well. The solution was to simply recreated the same function with a new name and for whatever magical reason that worked. The function signature was the same, the order of variables, variable names, the test conditions, everything in the body of the new function is the same.

What side-effects arise from setting a Long variable equal to False?

I am working on a piece of legacy code at work and I ran into a variable assignment that raises some questions for me. The variable PortOpen was declared with its type set as Long, and later in the code it was set equal to False. Since the integer value of False is 0, I assume that this will just mean the PortOpen will be 0 until it is modified, but I am suspicious that this might introduce some subtle bugs. A Long is twice the size of a Boolean in this case, so is there any possibility for an error when later using PortOpen in a logic comparison? Or, just in general, are there any quirks or other effects of using this type of variable assignment?
This is of course a bad thing as it is confusing for a person reading the code, but as long as you use 0/False for the false values and -1/True for true values the program should work fine.
You need to watch out for using 1 for True, as that will give you ambigous results. 1 (or in fact any value other than 0) will give you True in logical comparisons, so this will display "True":
Dim myvar As Long
myvar = 2
If myvar Then
MsgBox "True"
Else
MsgBox "False"
End If
However, the problem arises when you apply a "Not" to this expression. Generally you would expect "Not True" to be "False", but the following code will display "True":
Dim myvar As Long
myvar = 2
If Not myvar Then
MsgBox "True"
Else
MsgBox "False"
End If
So, apart from being bad for readability of your code, using Integer or Long for booleans CAN lead to errors in your code.
As you say PortOpen will be 0 after the automatic conversion of True to a Long, there are no other side effects of this assignment.
Aside from being bad practice & confusing for others the only other potential problem would be any assumption that PortOpen = 1 = True which is not the case as Clng(True) is -1.
Personally I would replace the assignemtnet with 0 or a 0 CLOSED symbolic constant/enum.

Resources