Compiler Interperets All Variables as Incorrectly Defined

Previous topic - Next topic

Nucleus

I have just begun to use the GLBasic programming language, and have noticed that all variables are seen by the compiler to have some sort of error. This was what I saw when I copied and pasted a program that was to print multiple variables:

"Hello, World!.gbas"(18) warning : probably unassigned variable : a$
"Hello, World!.gbas"(18) warning : probably unassigned variable : b$
"Hello, World!.gbas"(18) warning : probably unassigned variable : c
"Hello, World!.gbas"(19) warning : probably unassigned variable : d$
"Hello, World!.gbas"(18) error : variable is not explicitly defined : a$


It would be greatly appreciated if anybody could help me solve this problem.
                                                                                                                                                                                     Thank you,
                                                                                                                                                                                       -Nucleus

okee

In the Menu Click Project > Options and untick Explicit Declarations
but a better option would be to declare the variables as it will save a lot of headache
later on
Android: Samsung Galaxy S2 -  ZTE Blade (Orange San Francisco) - Ainol Novo 7 Aurora 2
IOS: 2 x Ipod Touch (1G)

Moru

Yes, all examples are done as simple as possible. This often means leaving out the variable declarations.

Explicit declarations are a pretty late addition to GLBasic so all old examples will need this.

CW

"Declare Variables" means to state each variable as local, global, or Constant; and also to indicate the data type. (Integer which is %, float which is #, string which is $.)

Declaring your variables is easy to do and it can help you dodge a lot of baffling errors due to typos, dropped caps, or misremembered names. You can disable explicit declarations if you want to, but I rarely do. Here is an example using explicit definitions of the various kinds.

Code (glbasic) Select

GLOBAL Cliant_Name$ = "Mary Ann"  // Global variables are visible throughout your program.
GLOBAL Payday# = 273.25
LOCAL Day%         // Local variables are visible only within the current section of code. A function, for example,
//                    would not see or be able to change this variable which is declared in the body. The body can not see
//                    or change variables declared as local within a function. A good rule of thumb is to try to avoid
//                    declaring global variables when you can. Use global variables only when it makes strong sense to do so.                                       

CONSTANT Sunday = 0, Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6
CONSTANT Days_In_Week = 7

LOCAL Money_Spent_On_Day#[]
DIM Money_Spent_On_Day[Days_In_Week]  // This is an array. Arrays always start counting at zero, but define as though counting from one.
//                                       The days of the week run from zero to six, but the array is dimensioned using 7 (which is 6+1)
//                                       Failing to dimension arrays properly is a very common error which will cause your program to
//                                       shut down and quit without any error messages. Whenever that happens, instantly suspect
//                                       an overflow error on one of your arrays.

Money_Spent_On_Day[Wednesday] = 36.27  // This is exactly the say as saying "Money_Spent_On_Day[3]", but using constants makes it a easier to read and follow the logic.
Money_Spent_On_Day[Thursday] = 9.85
Money_Spent_On_Day[Saturday] = 115.29
Money_Spent_On_Day[Sunday] = 17.00

LOCAL Total_Spent# = 0.0 // Will hold the sum of the weeks expenses. 
//                          In general it is a good idea to declare all of your variables at the top. But you can declare them just before they are used.

// In the next three commands, we add up all of the money spent over the course of the week.
// This is a FOREACH command which is used on arrays and is very powerful.
// You can add each day up explicitly if you wish, but see how compact this method is.

FOREACH payout IN Money_Spent_On_Day[]       // There is nothing special about the word 'payout'. It is a pointer, but I could have called it anything.
Total_Spent = Total_Spent + payout   // A shorter way to write this line is with the increment command: Try, INC Total_Spent,payout
NEXT

PRINT Cliant_Name$ + " spent $" + Total_Spent + " this week.",30,50
PRINT "She has $" + (Payday - Total_Spent) + " left for savings.",30,70

SHOWSCREEN
KEYWAIT
END


If the default mouse-font is too small to read, you may want to create a larger font and load it at the start of the program.
Creating your own fonts is very easy using the built in utility (once you see how it is done.)
But I won't get into than now, as it would take me off-topic to your question for this thread.

Happy Coding!
-CW

Moru

Thankyou CW, I totally forgot to write that part of my post :-)

CW

I forgot to mention STATIC and why you might want to use it. Static is important to understand and goes hand-in-hand with Local. 

-CW

Moru

Static is not important to learn in the start though.

Quick info is that STATIC is similar to LOCAL except the information stays in the variable until the program shuts down.

This means that a function can have variables that retains the information for each call. For example a counter of how many times the function has been called so a recursive function knows when to stop calling itself.

Another use could be a function that paints an object on screen. The function could be called with
Code (glbasic) Select
draw_turtle("init", x, y)
first time and save the location x and y as static variables. The second time you call the function it would be enough with
Code (glbasic) Select
draw_turtle("forward")
draw_turtle("turn_left")

because it remembers the location from the last call. (turtle grafics from really old-school basic :-)

CW

Thank you, Moru.  Those are excellent examples for STATIC variable use. (I especially liked the 'Turtle' reference. )  :good:

Allow me to round out this thread by exploring the subject a little deeper.

What follows is an example for which you will need to understand the finer points of Global, Local and Static variables in order to understand the program behavior.

I use the variables in odd ways in which an actual program never should. I do so in order to demonstrate important properties regarding the nature of Global, Static and Local variables.
Code (glbasic) Select


SETSCREEN 1000,300,0
GLOBAL fw%,fh%    // Here is good use of a Global variable. (We will use the font height to format printed output nicely, and it will work nicely even if you create a larger font.)
GETFONTSIZE fw,fh // Returns the font size, which is useful for formatting text.
fh=fh+5 // Let's add five pixels to space the lines of text out nicely.

GLOBAL Global_CNT% = 0
LOCAL  LocalString$ = " Polo!"  // Notice this variable name, then look in the subroutine.

CLEARSCREEN RGB(10,10,110)

REPEAT

GOSUB Example_Sub

UNTIL Global_CNT = 10

PRINT LocalString$,10,Global_CNT*(fh)  // Which saying will this command print out, "Maro" or "Polo"?

SHOWSCREEN
KEYWAIT
END

// ------------------------------------------------------------- //
// ---  EXAMPLE_SUB  ---
// ------------------------------------------------------------- //
SUB Example_Sub:

LOCAL LocalString$ = "Marco!" // The variable name is reused. Will this cause problems for its use in the Main Body?
//                                No! To the main body, it's value is still "Polo".
LOCAL Sub_Local_CNT%
STATIC Static_CNT%

PRINT  LocalString$+"    Global_CNT = " + Global_CNT + ": Sub_Local_CNT = "+Sub_Local_CNT+": Static_CNT "+Static_CNT,10,(Static_CNT*fh)

INC Global_CNT,1       // This command is the same as saying Global_CNT=Global_CNT+1
INC Sub_Local_CNT,1
INC Static_CNT,1

ENDSUB // EXAMPLE_SUB

//   ----------------------------------------------------------------------------------------- // 
//   ---  EXPLANATION  ---
//   ----------------------------------------------------------------------------------------- // 
// 
//  Local variables cannot be seen outside of the area in which they were declared.
//  LocalString$ = 'Polo' was defined in the main body, but it is completely invisible
//  to the subroutine. The sub even reuses the same variable name for "Marco" (which
//  is not good programing practice.) Then, when the main eventually uses LocalString$
//  it is the original 'Polo' (and not Marco) which is seen.
//
//  To all sections of the program, outside LOCAL variables do not exist.
//
//  It is the property of LOCAL variables to be preserved until the section of the program which
//  declared them ends. This is as true for subs and functions is it is for the main program. Just as
// the local variable assigned "Polo" in the main body was preserved when the sub was called, so
// too LOCAL variables which you declare from within a sub or function will be preserved on return
// from other subs and functions which it calls. The local variables are only lost when the sub or
// function (or main) which declared them ends.
//
//  -------------- Important Points ------------------------
//
//  * LOCAL protects important variables and prevents them from being corrupted by other sections 
//     of the program (as can happen with GLOBAL.)
//  * You can reuse variable names using local variables, but it is considered poor coding practice to do so.
//  * Local variables are dismissed when the sub or function exits, but not if a temporary detour
//     is taken to another sub or function.
//     The variables being dismissed when the sub ends is why the variable 'Sub_Local' kept getting
//     reset and never incremented beyond 1 in the example program; yet the the word "Polo",
//     assigned to the local variable declared in the main body stay active until the program itself ended.
//  * The local value declared within the main program was protected even when the variable name
//     was repeatedly reused by the sub.
//  * If you need to preserve a value within a sub or function, use 'STATIC' instead.
//     I used a static variable to preserve the Y-print position for each successive print statement output by the sub.
//     (That is a good use for a static variable.) You can use 'GLOBAL', but Global variables should be avoided when
//     possible. Even so, there are times when using a Global variable just makes good sense.
// 
//   ---------------------------------------------------------------------------------------- // 



When you look at the screen-snapshot below, notice how the value of the local variable Sub_Local_CNT never
increases, even though ALL of the variables (the Global, the Local and the Static) are incremented in the subroutine.
Why is that?

It looks as though the local variable is lost each time the sub exits, and reset each time the sub is called, yet
the static (and global) variables keep getting larger. Their values are preserved.

Notice too, how the variable called LocalString$ is defined as "Polo" in the main sub, then the same variable name is
reused in the subroutine with the word "Marco", yet following that, when the main sub uses it again, 'Polo" is seen.

The Local variables declared by the sub are lost then the sub ends, but the local variable declared by the main program is not.
Actually in both cases local variables are handled the same. Anytime a sub or a function calls another sub or function, local value as preserved and useable when program control returns. The locals are *only* discarded then the sub or function (or main) actually ends. For my example program the sub ends each cycle, while the main merely takes a temporary detour to the sub.

A detailed explanation on why these things are true is given at the bottom of the example program listing.

-CW