Jump to content

included functions - am I doing it right?


LoWang
 Share

Recommended Posts

Hello, I have a file with functions which I usually include to my scripts. I found out that I have to be carefull about variables used in the functions because they can overwrite global variables with the same name used in the host script, so I now declare them "local" in the first line of the defined function. Is this as it should be?

Also those functions sometimes use global variables which may not be declared always, so I add "global $var" to ensure it is there at least empty to avoid script error. I think it should work, but just tell me if my logic is OK or I miss something. Thanks

Link to comment
Share on other sites

  • Moderators

LoWang,

When you write UDFs to be used as #include files (which is basically what you are doing here) you have to take great care to avoid the very problems that you mention. ;)

A couple of tips:

- Use as few Global variables in the functions as possible. If you must use Global variables, make sure they have a suitably unique name - I usually use something like _UDFName_FunctionName - to reduce the risk of them getting overwritten by other parts of the script.

- Declare all other variables within the function as Local as you are doing - AutoIt does this automatically, but it is better practice to make it explicit.

You might also find the Variables - using Global, Local and ByRef tutorial in the Wiki an interesting read. :)

5M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Local variables are fine as long as you don't want to access them outside the function (main script or another function).

If you have to define global variables in your function I would suggest to use a prefix so you don't overwrite an already existing global variable by accident.

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

- Declare all other variables within the function as Local as you are doing - AutoIt does this automatically, but it is better practice to make it explicit.

How do you mean it? If I have a script which has something like $a=1 in the main body and then I use an included function which uses $a variable in a for cycle for example. Then this variable is overwritten in the main script! And that's why I should use "local" in the func to avoid this. So what do you mean by Autoit doing it automatically? Edited by LoWang
Link to comment
Share on other sites

"automatically" means that AutoIt defines the variable on first access if not already defined.

$a = 1
let's AutoIt define the variable $a and assing the value. 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

  • Moderators

LoWang,

If I have a script which has something like $a=1 in the main body and then I use an included function which uses $a variable in a for cycle for example. Then this variable is overwritten in the main script!

No, this will not happen - even if you do not specify the scope of the variables. As you can see here. :)

For $a = 1 To 3
    ConsoleWrite("$a before function = " & $a & @CRLF)
    _Func()
    ConsoleWrite("$a after function  = " & $a & @CRLF)
Next

Func _Func()
    For $a = 1 To 3
        ConsoleWrite("$a in function = " & $a & @CRLF)
    Next
EndFunc

The result:

$a before function = 1
$a in function = 1
$a in function = 2
$a in function = 3
$a after function  = 1
$a before function = 2
$a in function = 1
$a in function = 2
$a in function = 3
$a after function  = 2
$a before function = 3
$a in function = 1
$a in function = 2
$a in function = 3
$a after function  = 3

Did you read the Wiki tutorial I linked to? All of these questions are answered in there, so please do read it. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Melba23,

AutoIt3 does an implicit local declaration on the counter variable on the For loop. Your example only shows that Local effect with using a For loop. It is not consistent variable behavior to use as an example. It displays the rather unusual aspect of the For loop.

This example shows the natural behavior of a variable which has a dimmed scope by default.

$a = 1
ConsoleWrite("$a before function = " & $a & @CRLF)

_Func()

ConsoleWrite("$a after function  = " & $a & @CRLF)

Func _Func()
    $a = 2
EndFunc

The $a variable is global since first assignment is dimmed in a global section of the script. The function call sees $a is dimmed and since $a is already set in global scope, then $a in the function is treated as the same global $a. So, $a changes from 1 to 2.

I hope my correction does not offend you as it is nothing personal.

;)

Link to comment
Share on other sites

  • Moderators

MHz,

You are quite correct - and I am not offended in the least. ;)

This is why I always recommend using explicit Global/Local declarations for all variables - and using descriptive names for them! :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

LoWang,

...so I now declare them "local" in the first line of the defined function. Is this as it should be?

Should is not the correct way to look at this IMO. It is rather ideal if variables outside functions are all global and all variables inside functions are local. There may be minor times when when a dimmed variable in a function is suitable. You have made the right choice by using Local on those function variables that you want to keep local. Adding to the 1st line is what I do as you can do a quick review of the local variables without needing to search through all the function code to see what is declared local which of course is just a preference decision.

Also those functions sometimes use global variables which may not be declared always, so I add "global $var" to ensure it is there at least empty to avoid script error. I think it should work, but just tell me if my logic is OK or I miss something. Thanks

Most functions I expect to only have local variables. If not, then review if you could have done the functions different as to make those function variables more local if possible. It may even mean the functions or a entire script rewrite is needed if the variables are not handled well with scope i.e a design issue of the script. Using the keyword Global in a function is considered not good and needs consideration on how if possible to avoid doing that. ;)
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...