#175755 - 2007-04-27 03:27 PM
Variable Basics
|
tylan
Starting to like KiXtart
Registered: 2005-11-17
Posts: 115
Loc: Johnstown, PA
|
I've read the kix help, and I'm still not sure when to declare a variable as local or global.
This all started because I was using @TICKS to measure my script execution time, and I couldn't get the answer. I thought that my script would have worked find with "$START = @TICKS" defined at the beginning of my script. However, it didn't work correct until I declared my variables as local using the DIM command.
Could I get a little help on "DIM for Dummies"
|
|
Top
|
|
|
|
#175757 - 2007-04-27 03:42 PM
Re: Variable Basics
[Re: tylan]
|
Glenn Barnas
KiX Supporter
   
Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
|
Simplest rule is:
Don't declare your vars = GLOBAL Declare as GLOBAL, and the contents of the variable are visible to all parts of your program, including other functions, and scripts in other files executed by CALL commands.
Declare via DIM, and the contents of the variable are only visible in the segment where they were defined. This DOES include other scripts that are CALLed, but not inside functions.
For example, try this:
Global $X
Dim $Y
$X = "X-Var"
$Y = "Y-Var"
; Show current contents
"X=" $X ?
"Y=" $Y ?
; Call a function - throw away return value
$ = TestFunc()
; Show contents after calling TestFunc
"X=" $X ?
"Y=" $Y ?
; Call the function, passing an argument, and store the result in $Y
$Y = TestFunc($Y)
; Show contents after calling TestFunc again
"X=" $X ?
"Y=" $Y ?
; Define the function
Function TestFunc(OPTIONAL $Arg)
; Show contents of vars
"X=" $X ? ; this should display the GLOBAL var
"Y=" $Y ? ; this should display nothing
"Arg=" $Arg ? ; This is passed to func
$TestFunc = "Func-Val" ; return data from the function
EndFunction
This simple example shows the relationship of DIM and GLOBAL.
Generally, you want to DIM everything (good practice), pass arguments to functions, and declare as GLOBAL only things that every function should be able to view AND MODIFY!
Glenn
_________________________
Actually I am a Rocket Scientist!
|
|
Top
|
|
|
|
#175758 - 2007-04-27 03:47 PM
Re: Variable Basics
[Re: Glenn Barnas]
|
tylan
Starting to like KiXtart
Registered: 2005-11-17
Posts: 115
Loc: Johnstown, PA
|
Just to verify...
$X=1 <--- That's global, right? If I don't use DIM or GLOBAL an implicitly declared variable is GLOBAL?
|
|
Top
|
|
|
|
#175761 - 2007-04-27 03:59 PM
Re: Variable Basics
[Re: Glenn Barnas]
|
tylan
Starting to like KiXtart
Registered: 2005-11-17
Posts: 115
Loc: Johnstown, PA
|
So, what's the big deal with global variables? If I don't reuse variable names, what's the problem? (Since we aren't talking face to face, I feel the need to mention that I'm not disagreeing. I'm just trying to understand this better.)
|
|
Top
|
|
|
|
#175765 - 2007-04-27 04:44 PM
Re: Variable Basics
[Re: tylan]
|
Glenn Barnas
KiX Supporter
   
Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
|
The "problem" becomes apparent as: A. Your scripts get bigger (my largest project currently exceeds 10,000 lines) B. You create a library of script "snippets" that you reuse C. You build a library of functions (UDFs) that you write, or get publicly.
In single, small scripts, it usually isn't an issue. Most of us, however, find that small scripts tend to grow, and employing good coding practices from the beginning makes the projects more managable. We also leverage UDF libraries, and indiscriminate globals tend to mess them up.
I actually started using the following format for my declarations:
Dim $X, $I, $J ; temporary vars
Dim $aFiles, $File ; Array of file names & File enumeration var
Dim $Name ; Real name of user
Global $DEBUG ; flag indicating debug mode
Note how certain vars are defined together (temps), arrays and related index vars are paired, and global vars declared in ALL CAPS. (If their scope is VERY VISIBLE, the names should be too )
In functions that I write, I use a "$_name" format, and never use the "$_" format in front of a global, or in the main program module. On very large projects, or projects that will be publicly maintained, I use the Hungarian Variable Notation (google it) which defines standard ways to identify what kind of data will be held in a variable.
Glenn
_________________________
Actually I am a Rocket Scientist!
|
|
Top
|
|
|
|
#175766 - 2007-04-27 05:16 PM
Re: Variable Basics
[Re: Glenn Barnas]
|
tylan
Starting to like KiXtart
Registered: 2005-11-17
Posts: 115
Loc: Johnstown, PA
|
That's kinda where I thought you were going... Basically 'good habits'.
So, how long is a local variable good for? You said "Declare via DIM, and the contents of the variable are only visible in the segment where they were defined." So if you Declare via DIM within a nested IF..ENDIF the variable is gone after ENDIF?
Edited by tylan (2007-04-27 05:17 PM)
|
|
Top
|
|
|
|
#175769 - 2007-04-27 05:40 PM
Re: Variable Basics
[Re: tylan]
|
Witto
MM club member
   
Registered: 2004-09-29
Posts: 1828
Loc: Belgium
|
Yep
If NOT @LOGONMODE
Break On
Else
Break Off
EndIf
Dim $RC
$RC=SetOption("Explicit", "On")
$RC=SetOption("NoMacrosInStrings", "On")
$RC=SetOption("NoVarsInStrings", "On")
$RC=SetOption("WrapAtEOL", "On")
Dim $a
$a = 2
If $a = 2
Dim $b
$b = 3
$b ?
EndIf
; Error after this line if you delete the semicolon
;$b ?
|
|
Top
|
|
|
|
#175843 - 2007-05-01 11:01 AM
Re: Variable Basics
[Re: Glenn Barnas]
|
Richard H.
Administrator
   
Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
|
So, how long is a local variable good for? You said "Declare via DIM, and the contents of the variable are only visible in the segment where they were defined." So if you Declare via DIM within a nested IF..ENDIF the variable is gone after ENDIF?
No - visibility is within a program "module" or zone.
Just to clarify, because it's a bit ambiguous what Glenn's "No" is referring to.
You are correct in that the scope of a local variable is within the control structure. It can get pretty tricky though.
This script demonstrates scope in a single script, but there are three not-so-obvious points to be made:
Break ON
$=SetOption("Explicit","ON")
Dim $v,$counter
$v=1
"In main scope after local declaration, $$v="+$v+@CRLF
If "true"
"In 'IF' before local declaration - $$v="+$v+@CRLF
Dim $v
$v=2
"In 'IF' after local declaration - $$v="+$v+@CRLF
EndIf
"In main scope after returning from 'IF', $$v="+$v+@CRLF
While ($v=1 AND $counter<10)
"In WHILE construct $$v="+$v+" $$counter="+$counter+@CRLF
Dim $v
$v=3
$counter=$counter+1
Loop
"In main scope after returning from 'WHILE', $$v="+$v+@CRLF
The results from this script are:
In main scope after local declaration, $v=1 In 'IF' before local declaration - $v=1 In 'IF' after local declaration - $v=2 In main scope after returning from 'IF', $v=1 In WHILE construct $v=3 $counter= In WHILE construct $v=3 $counter=1 In WHILE construct $v=3 $counter=2 In WHILE construct $v=3 $counter=3 In WHILE construct $v=3 $counter=4 In WHILE construct $v=3 $counter=5 In WHILE construct $v=3 $counter=6 In WHILE construct $v=3 $counter=7 In WHILE construct $v=3 $counter=8 In WHILE construct $v=3 $counter=9 In main scope after returning from 'WHILE', $v=1
As you can see, the value of $v in the main scope ($v=1) if unaffected by the declarations in the control structure.
The three important things to note are:
- In the IF construct, the parent declaration of $V is visible until the local DIM in encountered in the script.
- The WHILE conditional part uses the variables from the parent scope, *not* the variables which are declared within the construct.
- There is a bit of KiXtart magic which ensures that the DIM in the WHILE loop is only actioned once, [b]when the construct is entered[/d]. Contrast this to the IF conditional, where the local declaration is actioned when it is encountered in the code. This is subtly different behaviour that could catch you out.
The scoping problem means that it is tricky to conditionally create a local variable, i.e. this won't work:
If Not IsDeclared($v)
Dim $v
EndIf
However, there is a rather surprising way around it:
$=Iif(IsDeclared($v),0,Execute("Dim $$v"))
Why is it surprising? Well, I would have expected "Execute()" to be a seperate scope, but it clearly isn't.
|
|
Top
|
|
|
|
Moderator: Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart
|
1 registered
(mole)
and 1300 anonymous users online.
|
|
|