Jump to content

Why use Local and Global at all?


WRP
 Share

Recommended Posts

17 hours ago, czardas said:

Parameters are treated as local variables unless you use the ByRef keyword, so function parameters do not collide with global variables. Remove ByRef from the code below and the global variable will remain zero. Also, scroll up the best coding practices page and you will see that the letter p is already used to indicate a pointer.

Global $g_iParam = 0

Go($g_iParam)
MsgBox(0, "", $g_iParam)

Func Go(ByRef $g_iParam) ; Remove ByRef to test the difference.
    $g_iParam = 1
EndFunc

 

Sure, I see what you mean in your example.
But, I would never expect someone the use the $g_ name for a parameter inside the called function.

As you point out, If ByRef is used, then, they might as well pass by scope rather than as a parameter.
And,
If ByRef WAS NOT USED, then it would be downright confusing and not a best practice to use the $g_ name for what is essentially a local variable.

 

My suggestion for the "$p_" was for the case where ByRef is used when one function calls another and a local variable is passed as a parameter.

In that case, any changes to the parameter in the called function would be made by reference to the original local variable in the calling function.
Thus, having a "$p_" parameter indicator would make it clear that changes to the $p_ parameter variable would change the value in the calling function.

This leads to the question, "Is by ref used much?"
I guess it saves storage.
Are there other reasons for using it?

Thanks for your insights.
Phil

 

 

 

Link to comment
Share on other sites

In response to earlier questions, the examples I posted are intended to demonstrate how these things work and are not real-world applications. Your conclusion is correct: there is no point in passing a global variable as a parameter - don't do it!

ByRef parameters are useful when you wish to modify a local variable using a second function. It prevents the creation of a copy of the variable once it has been modified within the second function. How you make use of this behaviour will depend on your design choice. For example; it is valid to pass a large array using ByRef, make modifications to it within the second function and finally undo the changes before returning to the calling function. Doing so will reserve memory without corrupting the original array. Whether this is a good design choice is an entirely different question.

A more likely scenario would be to use ByRef when a function recursively calls itself again and again. Just imagine a large array duplicated multiple times (on each recursive call) - it'll blow up!


Quote

My suggestion for the "$p_" was for the case where ByRef is used when one function calls another and a local variable is passed as a parameter.

In that case, any changes to the parameter in the called function would be made by reference to the original local variable in the calling function.
Thus, having a "$p_" parameter indicator would make it clear that changes to the $p_ parameter variable would change the value in the calling function.

@philkryder You worry too much. :D

Global $vTheWorld = 'everything'

Func Armageddon()
    Local $vTheWorld
    CheyenneMountainComplex($vTheWorld)
EndFunc

Func CheyenneMountainComplex(ByRef $vTheWorld)
    $vTheWorld = 'Are we alone?'
EndFunc

MsgBox(0, '', 'The world equals ' & $vTheWorld)

 

Edited by czardas
Link to comment
Share on other sites

3 minutes ago, trancexx said:

Actually, every variable that functions use as parameter should be passed as argument, no matter if it's global or not. Only global constants are free of that.

I wouldn't know that because I hardly ever use global variables, although it's good to know thanks. :)

Link to comment
Share on other sites

@trancexx If I understand you correctly, the following would be recommended syntax. I haven't noticed people using global variables as parameters before, but then again I have not been looking out for it. It seems that very few people follow this course, I wonder why. :think:

Global $g_bToggle = False

For $i = 1 To 2
    Toggle($g_bToggle)
Next

Func Toggle(ByRef $g_bToggle)
    If $g_bToggle Then
        ; something
    Else
        ; something else
    EndIf
    $g_bToggle = Not $g_bToggle
EndFunc

I'd rather it be less wordy. What if I have 100 or 1000 global flags?

Edited by czardas
Link to comment
Share on other sites

I think this means you should not only pass them to a function but return them as well:

Global $g_bToggle = False

For $i = 1 To 2
    $g_bToggle = Toggle($g_bToggle)
Next

Func Toggle(ByRef $g_bToggle)
    If $g_bToggle Then
        ; something
    Else
        ; something else
    EndIf
    Return Not $g_bToggle
EndFunc

Edit: If you have 100 or 1000 flags then store them in an Array and pass the Array forth/back.

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

10 hours ago, czardas said:

@trancexx If I understand you correctly, the following would be recommended syntax. I haven't noticed people using global variables as parameters before, but then again I have not been looking out for it. It seems that very few people follow this course, I wonder why. :think:

Global $g_bToggle = False

For $i = 1 To 2
    Toggle($g_bToggle)
Next

Func Toggle(ByRef $g_bToggle)
    If $g_bToggle Then
        ; something
    Else
        ; something else
    EndIf
    $g_bToggle = Not $g_bToggle
EndFunc

I'd rather it be less wordy. What if I have 100 or 1000 global flags?

As argument, not as parameter. Your example would look much better like this:

Global $g_bToggle = False

For $i = 1 To 2
    Toggle($g_bToggle)
Next

Func Toggle(ByRef $bToggle)
    If $bToggle Then
        ; something
    Else
        ; something else
    EndIf
    $bToggle = Not $bToggle
EndFunc

 

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

15 hours ago, water said:

If you have 100 or 1000 flags then store them in an Array and pass the Array forth/back.

I know that, but doing so could turn out to be the least desirable of two evils: the code has to be readable by a human.

12 hours ago, trancexx said:

As argument, not as parameter

Of course, thanks I understand. Even so, this seems to diminish some of the advantages of using globals: in so much that the syntax may become unwieldy and cumbersome when multiple globals require modification within a function. The small example above looks nice and neat, but I can't help wondering if this is simply a choice made for readability alone (without there being any other advantages). The disadvantages of ignoring this rule are also unclear to me. This being said, I appreciate it when someone corrects me. :)

Edit: How to solve this? (it's unsolvable)

Global $g_vWhatever = "hands off" ; do not try to modify this variable yourself

; user code
CallMe($g_vWhatever) ; I thought I said hands off $g_vWhatever.
MsgBox(0, "", $g_vWhatever)
; /user code

Func CallMe(ByRef $vWhatever)
    $vWhatever = $g_vWhatever ; try to prevent the misuse of $g_vWhatever (doesn't actually achieve much)
    ; some code
    $vWhatever = "I was passed as argument - meh!"
EndFunc

; broken patch - alpha (prevent the user from misusing the code)
Func CallCallMe() ; look, no parameters. ^^
    CallMe($g_vWhatever) ; The argument just appeared out of thin air (circular logic flaw).
EndFunc

I guess this must be an exceptional case, else a bad design concept - probably the latter. I'm so glad I avoid using global variables: they confuse/scare the hell out of me! :idiot: This is still very interesting.

Edited by czardas
Link to comment
Share on other sites

I believe I misunderstood trancexx earlier. Surely there is nothing wrong with modifying a global flag directly (without additional parameters). I just hadn't considered the idea that globals can also be modified using ByRef. It still seems a strange and unnecessary thing to do.

Edited by czardas
Link to comment
Share on other sites

I guess if you're used to code in language that does not have "Local" "Global" then you don't have to use this because you're used to  always  use something like "g_" or something similar that prevents names collision.

Anyway I am agree with this approach - not to use "Global" and "Local", but instead use prefix (including also "namespace" if I code in c++) for global variables.
It makes sense not to use "Global" or "Local". I did it before but no more. I use it only to declare more then one variable in the same line.

Note that I am not a professional. This is my personal opinion. I might be wrong. But agree there is no really need for Global / Local

 

Edited by Guest
Link to comment
Share on other sites

Local and Global are valuable, the only concern with the AutoIt implementation is that Local at level 0 (the script where it start) is treated as a Global for historical reason

Link to comment
Share on other sites

On 4/6/2016 at 0:53 PM, trancexx said:

As argument, not as parameter. Your example would look much better like this:

Global $g_bToggle = False

For $i = 1 To 2
    Toggle($g_bToggle)
Next

Func Toggle(ByRef $bToggle)
    If $bToggle Then
        ; something
    Else
        ; something else
    EndIf
    $bToggle = Not $bToggle
EndFunc

 

Yes this makes sense to me. The global can legitimately be passed into the function and then used by it's local name.
Other non-globals could also be passed in to the same function.

the reason for me sugestion of the $p prefix was to make it clear within the function that changes to the parameter would also reflect back to the calling function or mainline code.

Func Toggle(ByRef $bToggle)
    If $bToggle Then

Thus 
Func Toggle (ByRef $p_bToggle)... 
Would show that local changes within the function would be reflected in the calling function
Phil

 

Link to comment
Share on other sites

On 07/04/2016 at 8:49 PM, gil900 said:

Anyway I am agree with this approach - not to use "Global" and "Local", but instead use prefix (including also "namespace" if I code in c++) for global variables.

 

I am certainly not. I would rather be explicit than trying to second guess the internal workings of AutoIt. Be explicit, not implicit.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

1 hour ago, guinness said:

I am certainly not. I would rather be explicit than trying to second guess the internal workings of AutoIt. Be explicit, not implicit.

For me it explicit enough if the variable name not start with "g_".
It depends on how you used to read, see the code. But I understand your reason (you want to be more explicit).

Link to comment
Share on other sites

41 minutes ago, gil900 said:

For me it explicit enough if the variable name not start with "g_".

Okay, so if you have a project where you have multiple developers, this would be documented? Perhaps not, because as far as I'm concerned developers suck at writing documentation. At least Local/Global is documented in AutoIt and a programming convention. $g_ is just a styling convention that not everyone adheres to, because it's a best practice only.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Quote

Okay, so if you have a project where you have multiple developers, this would be documented?

You can write big note at the top of the project that explains about this point 

Link to comment
Share on other sites

4 minutes ago, gil900 said:

You can write big note at the top of the project that explains about this point 

I would like to actually see this project, because again from past experience developers just skip past such comments.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

This (write always Local ... in functions) is just a rule that makes the task harder.
You save yourself the small headache question - Where I should put this "Local... line" (It's not that simple, assuming you are careful to write it in lowest scope and outside of any loops).
if you don't need to write "Local ..." then you don't need to think about it..

 

Quote

I would like to actually see this project, because again from past experience developers just skip past such comments.

I have no such project currently

Link to comment
Share on other sites

5 hours ago, gil900 said:

if you don't need to write "Local ...

If you intend to combine your scripts with those written by other people, then the available name choices for local variables will be restricted if any of the libraries contain global variables. Then there is the annoyance of having to track down the bugs that are more likely to occur. Additionally your code would be potentially unstable and therefore unsuitable for others to use for these exact same reasons. In many ways it's a non-starter, or rather badly written code.

It's not something to worry too much about when you are an absolute beginner, but as soon as you learn some basics of programming, you should start to improve the way you write code. In the long term, you will benefit more from having made the extra effort.

Edited by czardas
Link to comment
Share on other sites

 

Quote

Additionally your code would be potentially unstable and therefore unsuitable for others to use for these exact same reasons.

czardas, You're right about your point.
if I write udf for use by others, I will follow this standard. (Hope it is written correctly) .

This is about Autoit. In other languages that does not have "Local"/"Global" keyword I am grateful that I do not need to worry about it

 

Quote

If you intend to combine your scripts with those written by other people, then the available name choices for local variables will be restricted if any of the libraries contain global variables.

If you're used to always read the other code you include before using it and keep an eye on every global variable in that code(that  you include) and change their name in a case then you are safe.

This is one effort that you must do at the include stage/step. This is compared to more then one effort that you must do if you don't do it (write always Local ... in functions )


 

 

Edited by Guest
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...