GW Basic default variable initialization - variables

I'm working with legacy code and ran across something that I haven't been able to explain after several days of looking up tutorials and handbooks for GW Basic: a variable (P9%) is used in a comparison on line 530 (IF P9% <> 0) before the code would reach its definition on line 860. It's not a complex piece of code, only ~1200 lines total, so I am confident that I haven't missed any goto or gosub or anything that would reach 860 earlier than this comparison.
I am curious as to how this has been effecting the program as it runs. Most of my experience is with c++ where this sort of thing wouldn't compile, and if it did an unassigned variable could potentially contain anything that would fit, but I have no idea what kind of default assignment is given to a variable in Basic.

It has been many years since I wrote much in gwbasic!
If I remember correctly the variable is assigned a zero value in that case. Gwbasic (and Qbasic I think) assigns a default value to all variables when first referenced, this is usually zero or the empty string for a string variable.
Interestingly when creating an array using the DIM statement, all the items in the array are also initialised this way.
Even with this mechanism it is usually better to initialise a variable, just to be clear what is happening.
Many programmers of the era writing for gwbasic omitted as much as they could to minimise the amount of memory used by the program instructions so they had more for other stuff. So that may be why it's not initialised.

Related

Is it possible to make Stata throw an error by default when a global macro is not defined, instead of a missing string?

A feature of Stata that is sometimes inconvenient is that calling a non-defined macro returns the missing value . [edit: Stata actually returns a missing string "", not a numerical missing value], instead of throwing an error.
A piece of code, whose correct execution requires the definition of the macro, may just run giving incorrect results if the macro name is misspelled.
E.g.: having defined
global $options = , vce(robust), when
afterwards one writes reg y x $opt instead of reg y x $options the program runs anyway and it may be difficult to realise that the vce() option was not considered.
Is there any way to force Stata to issue an error in this case or is there some useful trick/best practice that can be used to reduce the risk of incurring this sort of mistake?
The feature is described incorrectly. A macro that is undefined is evaluated as an empty string, conventionally written "", i.e. the delimiters " " contain nothing, or -- if you prefer -- nothing is contained between them.
A macro that is undefined is not ever evaluated as numeric system missing, written as a period . (call it dot or stop if you want).
You would see system missing if the macro were set to contain something else that was system missing, which is entirely different. Saved results from programs, for example, might be system missing.
One way to understand this is that macros in Stata contain strings, not numeric values; the fact that some macros have a numeric interpretation is something else. So, an undefined macro is evaluated as an empty string.
Stata programmers learn to use this feature constructively as a way of allowing defaults when macros are undefined and other choices when they are defined.
You are correct that the feature is a source of bugs, as when a spelling mistake leads Stata to see a name that isn't defined and just ignores the reference. The bug is still the programmer's bug, not Stata's.
So, what can you do, apart from check your code as usual? You can always check whether a macro is defined, as in
if "$options" == "" {
* do something
}
else {
* do something else
}
Conversely,
if "$options" != ""
is a test for content.
Alternatively, you could use string scalars. Here is an experiment:
. sysuse auto, clear
(1978 Automobile Data)
. scalar foo = ", meanonly"
. summarize mpg `=scalar(foo)'
. ret li
scalars:
r(N) = 74
r(sum_w) = 74
r(sum) = 1576
r(mean) = 21.2972972972973
r(min) = 12
r(max) = 41
. summarize mpg `=scalar(bar)'
bar not found
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
mpg | 74 21.2973 5.785503 12 41
In this case, there was an error message when an undefined scalar was referred to, but the command was executed any way.
Personally, as a long-term (1991- ) and high intensity Stata user, I just use macros routinely and regard being occasionally bitten by bugs of this kind as a very small price to pay for that. I have not ever used string scalars in this sense before trying to answer this question.
It's a different argument, but I regard using global macros in this way as poor programming style. There are general arguments across programming for minimizing the use of globally declared entities. Local macros are the beasts of choice.

SonarLint - questions about some of the rules for VB.NET

The large majority of SonarLint rules that I've come across in Java seemed plausible and justified. However, ever since I've started using SonarLint for VB.NET, I've come across several rules that left me questioning their usefulness or even whether or not they are working correctly.
I'd like to know if this is simply a problem of me using some VB.NET constructs in a suboptimal way or whether the rule really is flawed.
(Apologies if this question is a little longer. I didn't know if I should create a separate question for each individual rule.)
The following rules I found to leave some cases unconsidered that would actually turn up as false-positives:
S1871: Two branches in the same conditional structure should not have exactly the same implementation
I found this one to bring up a lot of false-positives for me, because sometimes the order in which the conditions are checked actually does matter. Take the following pseudo code as example:
If conditionA() Then
doSomething()
ElseIf conditionB() AndAlso conditionC() Then
doSomethingElse()
ElseIf conditionD() OrElse conditionE() Then
doYetAnotherThing()
'... feel free to have even more cases in between here
Else Then
doSomething() 'Non-compliant
End If
If I wanted to follow this Sonar rule and still make the code behave the same way, I'd have to add the negated version of each ElseIf-condition to the first If-condition.
Another example would be the following switch:
Select Case i
Case 0 To 40
value = 0
Case 41 To 60
value = 1
Case 61 To 80
value = 3
Case 81 To 100
value = 5
Case Else
value = 0 'Non-compliant
There shouldn't be anything wrong with having that last case in a switch. True, I could have initialized value beforehand to 0 and ignored that last case, but then I'd have one more assignment operation than necessary. And the Java ruleset has conditioned me to always put a default case in every switch.
S1764: Identical expressions should not be used on both sides of a binary operator
This rule does not seem to take into account that some functions may return different values every time you call them, for instance collections where accessing an element removes it from the collection:
stack.Push(stack.Pop() / stack.Pop()) 'Non-compliant
I understand if this is too much of an edge case to make special exceptions for it, though.
The following rules I am not actually sure about:
S3385: "Exit" statements should not be used
While I agree that Return is more readable than Exit Sub, is it really bad to use a single Exit For to break out of a For or a For Each loop? The SonarLint rule for Java permits the use of a single break; in a loop before flagging it as an issue. Is there a reason why the default in VB.NET is more strict in that regard? Or is the rule built on the assumption that you can solve nearly all your loop problems with LINQ extension methods and lambdas?
S2374: Signed types should be preferred to unsigned ones
This rule basically states that unsigned types should not be used at all because they "have different arithmetic operators than signed ones - operators that few developers understand". In my code I am only using UInteger for ID values (because I don't need negative values and a Long would be a waste of memory in my case). They are stored in List(Of UInteger) and only ever compared to other UIntegers. Is this rule even relevant to my case (are comparisons part of these "arithmetic operators" mentioned by the rule) and what exactly would be the pitfall? And if not, wouldn't it be better to make that rule apply to arithmetic operations involving unsigned types, rather than their declaration?
S2355: Array literals should be used instead of array creation expressions
Maybe I don't know VB.NET well enough, but how exactly would I satisfy this rule in the following case where I want to create a fixed-size array where the initialization length is only known at runtime? Is this a false-positive?
Dim myObjects As Object() = New Object(someOtherList.Count - 3) {} 'Non-compliant
Sure, I could probably just use a List(Of Object). But I am curious anyway.
Thanks for raising these points. Note that not all rules apply every time. There are cases when we need to balance between false positives/false negatives/real cases. For example with identical expressions on both sides of an operator rule. Is it a bug to have the same operands? No it's not. If it was, then the compiler would report it. Is it a bad smell, is it usually a mistake? Yes in many cases. See this for example in Roslyn. Should we tune this rule to exclude some cases? Yes we should, there's nothing wrong with 2 << 2. So there's a lot of balancing that needs to happen, and we try to settle for an implementation that brings the most value for the users.
For the points you raised:
Two branches in the same conditional structure should not have exactly the same implementation
This rule generally states that having two blocks of code match exactly is a bad sign. Copy-pasted code should be avoided for many reasons, for example if you need to fix the code in one place, you'll need to fix it in the other too. You're right that adding negated conditions would be a mess, but if you extract each condition into its own method (and call the negated methods inside them) with proper names, then it would probably improves the readability of your code.
For the Select Case, again, copy pasted code is always a bad sign. In this case you could do this:
Select Case i
...
Case 0 To 40
Case Else
value = 0 ' Compliant
End Select
Or simply remove the 0-40 case.
Identical expressions should not be used on both sides of a binary operator
I think this is a corner case. See the first paragraph of the answer.
"Exit" statements should not be used
It's almost always true that by choosing another type of loop, or changing the stop condition, you can get away without using any "Exit" statements. It's good practice to have a single exit point from loops.
Signed types should be preferred to unsigned ones
This is a legacy rule from SonarQube VB.NET, and I agree with you that it shouldn't be enabled by default in SonarLint. I created the following ticket in our JIRA: https://jira.sonarsource.com/browse/SLVS-1074
Array literals should be used instead of array creation expressions
Yes, it seems to be a false positive, we shouldn't report on array creations when the size is explicitly specified. https://jira.sonarsource.com/browse/SLVS-1075

VBA Overflow Error 6 -- simply when terminating a class

I am trying to debug code that typically functions properly and has been in production for a while, but has some errors associated with particular case runs.
I have a class called "Guarantee", and a variable / object, "myDem", which is of that class. The class has an associated function called "NumberOfGuaranteeDays". The first image given below shows a Long variable called "numRows" being assigned to this function call on "myDem". When this assigment is made -- and, therefore, the "NumberOfGuaranteeDays" function is called -- I receive an Overflow error.
After the function call "NumberOfGuaranteeDays" is run, which is a fairly complex call with many sub-functions itself, then class attempts to terminate itself, and return the value (the number of days, which is an integer... in this case it's 32561). It is during this termination step and the assignment of "numRows" to the value 32561, when the error occurs.
Here I simply demonstrate that the very next step within the code, if I step through it, is where the error message is returned back to me.
Finally I wanted to provide "proof" that the value assigned to "numRows" is 32561, of type Integer, which can acceptably be assigned to a Long. Note in the far right in the watch part of the window, the value "res" is the value which is returned from the "NumberOfGuaranteeDays" call, which is then assigned to the variable "numRows".
As far as I can tell, there are only 2 possibilities for why a crash can be occurring:
There is an error in the attempt to terminate the class. I don't understand how this could lead to an "overflow" error, though.
There is an error in the assignment of the value calculated from "NumberOfGuaranteeDays" to the variable "numRows". This sort of assignment could potentially have an overflow, but not in this case. The return from "NumberOfGuaranteeDays", which is the "res" integer set at 32561, is assigned to "numRows", which is a Long.
So, since neither of these possibilities that I can imagine make sense, I figure there must be another possibility I cannot see. Thank you all in advance for the help!
I opted to put in cut & pasted images instead of writing as code because so much of what's critical to understanding the steps is seeing "proof" of where I am in the debugging stages. If actual code snippets would help, let me know.
Thank you!
Mike

can a variable have multiple values

In algebra if I make the statement x + y = 3, the variables I used will hold the values either 2 and 1 or 1 and 2. I know that assignment in programming is not the same thing, but I got to wondering. If I wanted to represent the value of, say, a quantumly weird particle, I would want my variable to have two values at the same time and to have it resolve into one or the other later. Or maybe I'm just dreaming?
Is it possible to say something like i = 3 or 2;?
This is one of the features planned for Perl 6 (junctions), with syntax that should look like my $a = 1|2|3;
If ever implemented, it would work intuitively, like $a==1 being true at the same time as $a==2. Also, for example, $a+1 would give you a value of 2|3|4.
This feature is actually available in Perl5 as well through Perl6::Junction and Quantum::Superpositions modules, but without the syntax sugar (through 'functions' all and any).
At least for comparison (b < any(1,2,3)) it was also available in Microsoft Cω experimental language, however it was not documented anywhere (I just tried it when I was looking at Cω and it just worked).
You can't do this with native types, but there's nothing stopping you from creating a variable object (presuming you are using an OO language) which has a range of values or even a probability density function rather than an actual value.
You will also need to define all the mathematical operators between your variables and your variables and native scalars. Same goes for the equality and assignment operators.
numpy arrays do something similar for vectors and matrices.
That's also the kind of thing you can do in Prolog. You define rules that constraint your variables and then let Prolog resolve them ...
It takes some time to get used to it, but it is wonderful for certain problems once you know how to use it ...
Damien Conways Quantum::Superpositions might do what you want,
https://metacpan.org/pod/Quantum::Superpositions
You might need your crack-pipe however.
What you're asking seems to be how to implement a Fuzzy Logic system. These have been around for some time and you can undoubtedly pick up a library for the common programming languages quite easily.
You could use a struct and handle the operations manualy. Otherwise, no a variable only has 1 value at a time.
A variable is nothing more than an address into memory. That means a variable describes exactly one place in memory (length depending on the type). So as long as we have no "quantum memory" (and we dont have it, and it doesnt look like we will have it in near future), the answer is a NO.
If you want to program and to modell this behaviour, your way would be to use a an array (with length equal to the number of max. multiple values). With this comes the increased runtime, hence the computations must be done on each of the values (e.g. x+y, must compute with 2 different values x1+y1, x2+y2, x1+y2 and x2+y1).
In Perl , you can .
If you use Scalar::Util , you can have a var take 2 values . One if it's used in string context , and another if it's used in a numerical context .

What's bad about the VB With/End With keyword?

In this question, a user commented to never use the With block in VB. Why?
"Never" is a strong word.
I think it fine as long as you don't abuse it (like nesting)
IMHO - this is better:
With MyCommand.Parameters
.Count = 1
.Item(0).ParameterName = "#baz"
.Item(0).Value = fuz
End With
Than:
MyCommand.Parameters.Count = 1
MyCommand.Parameters.Item(0).ParameterName = "#baz"
MyCommand.Parameters.Item(0).Value = fuz
There is nothing wrong about the With keyword. It's true that it may reduce readibility when nested but the solution is simply don't use nested With.
There may be namespace problems in Delphi, which doesn't enforce a leading dot but that issue simply doesn't exist in VB.NET so the people that are posting rants about Delphi are losing their time in this question.
I think the real reason many people don't like the With keyword is that is not included in C* languages and many programmers automatically think that every feature not included in his/her favourite language is bad.
It's just not helpful compared to other options.
If you really miss it you can create a one or two character alias for your object instead. The alias only takes one line to setup, rather than two for the With block (With + End With lines).
The alias also gives you a quick mouse-over reference for the type of the variable. It provides a hook for the IDE to help you jump back to the top of the block if you want (though if the block is that large you have other problems). It can be passed as an argument to functions. And you can use it to reference an index property.
So we have an alternative that gives more function with less code.
Also see this question:
Why is the with() construct not included in C#, when it is really cool in VB.NET?
The with keyword is only sideswiped in a passing reference here in an hilarious article by the wonderful Verity Stob, but it's worth it for the vitriol: See the paragraph that starts
While we are on identifier confusion. The with keyword...
Worth reading the entire article!
The With keyword also provides another benefit - the object(s) in the With statement only need to be "qualified" once, which can improve performance. Check out the information on MSDN here:
http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx
So by all means, use it.