# Functions

## Introduction and Simple Examples

A function is similar to a subroutine (Gosub) except that it can accept parameters (inputs) from its caller. In addition, a function may optionally return a value to its caller. Consider the following simple function that accepts two numbers and returns their sum:

```Add(x, y)
{
return x + y
}```

The above is known as a function definition because it creates a function named "Add" (not case sensitive) and establishes that anyone who calls it must provide exactly two parameters (x and y). To call the function, assign its result to a variable with the := operator. For example:

`Var := Add(2, 3)  ; The number 5 will be stored in Var.`

Also, a function may be called without storing its return value:

```Add(2, 3)
Add 2, 3  ; Parentheses can be omitted if used at the start of a line.```

But in this case, any value returned by the function is discarded; so unless the function produces some effect other than its return value, the call would serve no purpose.

Within an expression, a function call "evaluates to" the return value of the function. The return value can be assigned to a variable as shown above, or it can be used directly as shown below:

```if InStr(MyVar, "fox")
MsgBox "The variable MyVar contains the word fox."```

## Parameters

When a function is defined, its parameters are listed in parentheses next to its name (there must be no spaces between its name and the open-parenthesis). If a function does not accept any parameters, leave the parentheses empty; for example: `GetCurrentTimestamp()`.

ByRef Parameters: From the function's point of view, parameters are essentially the same as local variables unless they are defined as ByRef as in this example:

```Swap(ByRef Left, ByRef Right)
{
temp := Left
Left := Right
Right := temp
}```

In the example above, the use of ByRef causes each parameter to become an alias for the variable passed in from the caller. In other words, the parameter and the caller's variable both refer to the same contents in memory. This allows the Swap function to alter the caller's variables by moving Left's contents into Right and vice versa.

By contrast, if ByRef were not used in the example above, Left and Right would be copies of the caller's variables and thus the Swap function would have no external effect.

Since return can send back only one value to a function's caller, ByRef can be used to send back extra results. This is achieved by having the caller pass in a variable (usually empty) in which the function stores a value.

When passing large strings to a function, ByRef enhances performance and conserves memory by avoiding the need to make a copy of the string. Similarly, using ByRef to send a long string back to the caller usually performs better than something like `Return HugeString`.

If something other than a modifiable variable is passed to a ByRef parameter, the function behaves as though the keyword "ByRef" is absent. For example, `Swap(A_Index, i)` stores the value of A_Index in i, but the value assigned to Left is discarded once the Swap function returns.

The IsByRef function can be used to determine whether the caller supplied a variable for a given ByRef parameter.

Known limitations:

• It is not possible to pass properties of objects (such as `foo.bar`), Clipboard or other built-in variables to a function by reference. Instead, the function acts as though ByRef was omitted.
• Although a function may call itself recursively, if it passes one of its own local variables or non-ByRef parameters to itself ByRef, the new layer's ByRef parameter will refer to its own local variable of that name rather than the previous layer's. However, this issue does not occur when a function passes to itself a global variable, static variable, or ByRef parameter.
• If a parameter in a function-call resolves to a variable (e.g. `Var` or `++Var` or `Var*=2`), other parameters to its left or right can alter that variable before it is passed to the function. For example, `MyFunc(Var, Var++)` would unexpectedly pass 1 and 0 when Var is initially 0, even when the function's first parameter is not ByRef. Since this behavior is counterintuitive, it might change in a future release.
• ByRef is not directly supported in functions called by COM clients, or when calling COM methods. Instead, the script receives or must pass a wrapper object containing the VarType and address of the value.

## Optional Parameters

When defining a function, one or more of its parameters can be marked as optional. This is done by appending `:=` followed by the parameter's default value, which must be one of the following: `true`, `false`, a literal integer, a literal floating point number, or a quoted/literal string such as "fox" or "".

The following function has its Z parameter marked optional:

```Add(X, Y, Z := 0) {
return X + Y + Z
}```

When the caller passes three parameters to the function above, Z's default value is ignored. But when the caller passes only two parameters, Z automatically receives the value 0.

It is not possible to have optional parameters isolated in the middle of the parameter list. In other words, all parameters that lie to the right of the first optional parameter must also be marked optional. However, optional parameters may be omitted from the middle of the parameter list when calling the function, as shown below:

```MyFunc(1,, 3)
MyFunc(X, Y:=2, Z:=0) {  ; Note that Z must still be optional in this case.
MsgBox X ", " Y ", " Z
}```

ByRef parameters also support default values; for example: `MyFunc(ByRef p1 := "")`. Whenever the caller omits such a parameter, the function creates a local variable to contain the default value; in other words, the function behaves as though the keyword "ByRef" is absent.

## Returning Values to Caller

As described in introduction, a function may optionally return a value to its caller.

```MsgBox returnTest()

returnTest() {
return 123
}
```

If you want to return extra results from a function, you may also use ByRef:

```returnByRef(A,B,C)
MsgBox A "," B "," C

returnByRef(ByRef val1, ByRef val2, ByRef val3)
{
val1 := "A"
val2 := 100
val3 := 1.1
return
}
```

Objects and Arrays can be used to return multiple values or even named values:

```Test1 := returnArray1()
MsgBox Test1[1] "," Test1[2]

Test2 := returnArray2()
MsgBox Test2[1] "," Test2[2]

Test3 := returnObject()
MsgBox Test3.id "," Test3.val

returnArray1() {
Test := [123,"ABC"]
return Test
}

returnArray2() {
x := 456
y := "EFG"
return [x, y]
}

returnObject() {
Test := {id: 789, val: "HIJ"}
return Test
}
```

When defining a function, write an asterisk after the final parameter to mark the function as variadic, allowing it to receive a variable number of parameters:

```Join(sep, params*) {
for index,param in params
str .= param . sep
return SubStr(str, 1, -StrLen(sep))
}
MsgBox Join("`n", "one", "two", "three")```

When a variadic function is called, surplus parameters can be accessed via an object which is stored in the function's final parameter. The first surplus parameter is at `params[1]`, the second at `params[2]` and so on. As it is a standard Object, `params.Length()` can be used to determine the number of parameters.

Notes:

• The "variadic" parameter can only appear at the end of the formal parameter list.
• RegEx callouts cannot be variadic; the "variadic" parameter is tolerated but left blank.

While variadic functions can accept a variable number of parameters, an array of parameters can be passed to any function by applying the same syntax to a function-call:

```substrings := ["one", "two", "three"]
MsgBox Join("`n", substrings*)```

Notes:

• Numbering of parameters within the source array begins at 1.
• Optional parameters may be entirely omitted from the array.
• The array of parameters may contain named items when calling a user-defined function; in any other case, named items are not supported.
• The target function may also be variadic, in which case named items are copied even if they have no corresponding formal parameter.
• This syntax can also be used when calling methods or setting or retrieving properties of objects; for example, `Object.Property[Params*]`.

Known limitations:

• Only the right-most parameter can be expanded this way. For example, `MyFunc(x, y*)` is supported but `MyFunc(x*, y)` is not.
• There must not be any non-whitespace characters between the asterisk (`*`) and the symbol which ends the parameter list.

## Local and Global Variables

### Local Variables

Local variables are specific to a single function and are visible only inside that function. Consequently, a local variable may have the same name as a global variable and both will have separate contents. Separate functions may also safely use the same variable names.

All local variables which are not static are automatically freed (made empty) when the function returns, with the exception of variables which are bound to a closure.

Built-in variables such as Clipboard, ErrorLevel, and A_TimeIdle are never local (they can be accessed from anywhere), and cannot be redeclared.

Functions are assume-local by default. Variables accessed or created inside an assume-local function are local by default, with the following exceptions:

The default may also be overridden as shown below (by declaring the variable or by changing the mode of the function).

Force-local mode: If the function's first line is the word "local", all variable references are assumed to be local unless they are declared as global inside the function. Unlike the default mode, force-local mode has the following behavior:

• Super-global variables (including classes) cannot be accessed without declaring them inside the function.
• If the function is defined inside another function, the outer function's local and static variables cannot be accessed.
• The LocalSameAsGlobal warning is never raised for variables within a force-local function.

### Global variables

To refer to an existing global variable inside a function (or create a new one), declare the variable as global prior to using it. For example:

```LogToFile(TextToLog)
{
global LogFileName  ; This global variable was previously given a value somewhere outside this function.
FileAppend TextToLog "`n", LogFileName
}```

Assume-global mode: If a function needs to access or create a large number of global variables, it can be defined to assume that all its variables are global (except its parameters) by making its first line the word "global". For example:

```SetDefaults()
{
global
MyGlobal := 33  ; Assigns 33 to a global variable, first creating the variable if necessary.
local x, y:=0, z  ; Local variables must be declared in this mode, otherwise they would be assumed global.
}```

This assume-global mode can also be used by a function to create a global pseudo-array, such as a loop that assigns values to `Array%A_Index%`.

Super-global variables: If a global declaration appears outside of any function, it takes effect for all functions by default (excluding force-local functions). This avoids the need to redeclare the variable in each function. However, if a function parameter or local variable with the same name is declared, it takes precedence over the global variable. Variables created by the class keyword are also super-global.

### Static variables

Static variables are always implicitly local, but differ from locals because their values are remembered between calls. For example:

```LogToFile(TextToLog)
{
static LoggedLines := 0
LoggedLines += 1  ; Maintain a tally locally (its value is remembered between calls).
global LogFileName
FileAppend LoggedLines ": " TextToLog "`n", LogFileName
}```

A static variable may be initialized on the same line as its declaration by following it with `:=` followed by any expression. For example: `static X:=0, Y:="fox"`. Each static variable is initialized only once. Static variables are initialized in the order that they appear in the script file, but before the script's auto-execute section.

Assume-static mode: A function may be defined to assume that all its variables are static (except its parameters) by making its first line the word "static". For example:

```GetFromStaticArray(WhichItemNumber)
{
static
static FirstCallToUs := true  ; A static declaration's initializer still runs only once (upon startup).
if FirstCallToUs  ; Create a static array during the first call, but not on subsequent calls.
{
FirstCallToUs := false
Loop 10
StaticArray%A_Index% := "Value #" . A_Index
}
return StaticArray%WhichItemNumber%
}```

In assume-static mode, any variable that should not be static must be declared as local or global (with the same exceptions as for assume-local mode, unless force-local mode is also in effect).

Force-local mode can be combined with assume-static mode by specifying `local` and then `static`, as shown below. This allows the function to use force-local rules but create variables as static by default.

```global MyVar := "This is global"
DemonstrateForceStatic()

DemonstrateForceStatic()
{
local
static
MyVar := "This is static"
ListVars
MsgBox
}
```

### More about locals and globals

Multiple variables may be declared on the same line by separating them with commas as in these examples:

```global LogFileName, MaxRetries := 5
static TotalAttempts := 0, PrevResult```

A local or global variable may be initialized on the same line as its declaration by following it with `:=` followed by any expression. Unlike static initializers, the initializers of locals and globals execute every time the function is called, but only if/when the flow of control actually reaches them. In other words, a line like `local x := 0` has the same effect as writing two separate lines: `local x` followed by `x := 0`.

Because the words local, global, and static are processed immediately when the script launches, a variable cannot be conditionally declared by means of an IF statement. In other words, a declaration inside an IF's or ELSE's block takes effect unconditionally for all lines between the declaration and the function's closing brace. Also note that it is not currently possible to declare a dynamic variable such as `global Array%i%`.

## Dynamically Calling a Function

A function (even a built-in function) may be called dynamically via percent signs. For example, `%Var%(x, "fox")` would call the function whose name is contained in Var. Similarly, `Func%A_Index%()` would call Func1() or Func2(), etc., depending on the current value of A_Index.

Var in `%Var%()` can contain a function name or a function object. If the function does not exist, the default base object's Call method is called instead (and as usual, if this method is undefined, the __Call meta-function is invoked).

If the function cannot be called due to one of the reasons below, an exception is thrown:

• Calling a nonexistent function, which can be avoided by using `If IsFunc(VarContainingFuncName)`. Except for built-in functions, the called function's definition must exist explicitly in the script by means such as #Include or a non-dynamic call to a library function.
• Passing too few parameters, which can be avoided by checking IsFunc's return value (which is the number of mandatory parameters plus one). Note: Passing too many parameters is tolerated; each extra parameter is fully evaluated (including any calls to functions) and then discarded.

Finally, a dynamic call to a function is slightly slower than a normal call because normal calls are resolved (looked up) before the script begins running.

## Short-circuit Boolean Evaluation

When AND, OR, and the ternary operator are used within an expression, they short-circuit to enhance performance (regardless of whether any function calls are present). Short-circuiting operates by refusing to evaluate parts of an expression that cannot possibly affect its final result. To illustrate the concept, consider this example:

```if (ColorName <> "" AND not FindColor(ColorName))
MsgBox ColorName " could not be found."```

In the example above, the FindColor() function never gets called if the ColorName variable is empty. This is because the left side of the AND would be false, and thus its right side would be incapable of making the final outcome true.

Because of this behavior, it's important to realize that any side-effects produced by a function (such as altering a global variable's contents) might never occur if that function is called on the right side of an AND or OR.

It should also be noted that short-circuit evaluation cascades into nested ANDs and ORs. For example, in the following expression, only the leftmost comparison occurs whenever ColorName is blank. This is because the left side would then be enough to determine the final answer with certainty:

```if (ColorName = "" OR FindColor(ColorName, Region1) OR FindColor(ColorName, Region2))
break   ; Nothing to search for, or a match was found.```

As shown by the examples above, any expensive (time-consuming) functions should generally be called on the right side of an AND or OR to enhance performance. This technique can also be used to prevent a function from being called when one of its parameters would be passed a value it considers inappropriate, such as an empty string.

The ternary conditional operator (?:) also short-circuits by not evaluating the losing branch.

## Nested Functions

A nested function is one defined inside another function. For example:

```outer(x) {
inner(y) {
MsgBox(y, x)
}
inner("one")
inner("two")
}
outer("title")
```

A nested function is not accessible outside of the function which immediately encloses it, but is accessible anywhere inside that function, including inside other nested functions.

By default, a nested function may access non-dynamic local and static variables of any function which encloses it, but not ByRef parameters or variables which are created dynamically. Global declarations in the outer function also apply to nested functions, except where overridden by force-local.

If a function is declared force-local or assume-global, any local or static variables created outside that function are not directly accessible to the function itself or any of its nested functions.

Functions are assume-local by default, and this is true even for nested functions, even those inside an assume-static function. However, if the outer function is assume-global, nested functions behave as though assume-global by default, except that they can refer to local and static variables of the outer function.

A nested function which is assume-static can still refer to variables from the outer function, unless it is also force-local.

Dynamic variable references inside a nested function can resolve to variables from the outer function only if the nested function (or one of its own nested functions) also contains a non-dynamic reference to the variable.

Func can be used to retrieve a reference to a nested function, which can be called even after the outer function returns. Nested functions can also be passed by name to built-in functions such as SetTimer and Sort.

### Closures

A closure is a nested function bound to a set of free variables. Free variables are local variables of the outer function which are also used by nested functions. Closures allow one or more nested functions to share variables with the outer function even after the outer function returns.

To create a closure, pass the name of a nested function to Func. For example:

```make_greeter(f)
{
greet(subject)  ; This will be a closure due to f.
{
MsgBox Format(f, subject)
}
return Func("greet")  ; Create and return a closure.
}

g := make_greeter("Hello, {}!")
g.call("World")
```

A closure may also be created by passing the name of a nested function to a built-in function, such as SetTimer or Hotkey. For example:

```app_hotkey(hotkey, app_title, app_path)
{
activate()  ; This will be a closure due to app_title and app_path.
{
if WinExist(app_title)
WinActivate
else
Run app_path
}
Hotkey hotkey, "activate"
}
; Win+N activates or launches Notepad.
; Win+W activates or launches WordPad.
```

If a function creates free variables (that is, if any of its local variables are referenced by nested functions), all of that function's nested functions become closures. This is because any nested function can call any other nested function or create a closure for it by name.

Whenever a function name is resolved to a closure, a new closure is created even if one had already been created with the same set of free variables. Do not pass a closure by name to SetTimer, OnClipboardChange, OnExit, OnMessage or Gui.OnEvent if that closure needs to be later removed, since doing so requires passing the same object back. For example:

```timertest() {
x := "tock!"
tick() {
MsgBox x               ; x causes this to become a closure.
;SetTimer t, "Delete"  ; This would cause a circular reference.
}
SetTimer "tick", 1000      ; Creates a timer.
SetTimer "tick", "Delete"  ; Fails.
t := Func("tick")
SetTimer t, 1000           ; Creates a second timer.
SetTimer t, "Delete"       ; Deletes the second timer.
}
timertest()
```

It is best not to store a reference to a closure in any of the closure's own free variables, since that creates a circular reference which must be broken before the closure can be freed, such as by clearing the variable.

### Using Subroutines Within a Function

A function can also contain subroutines, which are more limited but may perform faster than nested functions. As with other subroutines, use Gosub to launch them and Return to return (in which case the Return would belong to the Gosub and not the function).

If a function uses Gosub to jump to a public subroutine (one that lies outside of the function's braces), all variables outside are global and the function's own local variables are not accessible until the subroutine returns. However, A_ThisFunc will still contain the name of the function.

Although Goto cannot be used to jump from inside a function to outside, it is possible for a function to Gosub an external/public subroutine and then do a Goto from there.

Although the use of Goto is generally discouraged, it can be used inside a function to jump to another position within the same function. This can help simplify complex functions that have many points of return, all of which need to do some clean-up prior to returning.

## Return, Exit, and General Remarks

If the flow of execution within a function reaches the function's closing brace prior to encountering a Return, the function ends and returns a blank value (empty string) to its caller. A blank value is also returned whenever the function explicitly omits Return's parameter.

When a function uses Exit to terminate the current thread, its caller does not receive a return value at all. For example, the statement `Var := Add(2, 3)` would leave `Var` unchanged if `Add()` exits. The same thing happens if a function causes a runtime error such as running a nonexistent file (when this error is not caught by a Try/Catch statement).

A function may alter the value of ErrorLevel for the purpose of returning an extra value that is easy to remember.

To call a function with one or more blank values (empty strings), use an empty pair of quotes as in this example: `FindColor(ColorName, "")`.

Since calling a function does not start a new thread, any changes made by a function to settings such as SendMode and SetTitleMatchMode will go into effect for its caller too.

The caller of a function may pass a nonexistent variable or array element to it, which is useful when the function expects the corresponding parameter to be ByRef. For example, calling `GetNextLine(BlankArray%i%)` would create the variable `BlankArray%i%` automatically as a local or global (depending on whether the caller is inside a function and whether it has the assume-global mode in effect).

When used inside a function, ListVars displays a function's local variables along with their contents. This can help debug a script.

## Style and Naming Conventions

You might find that complex functions are more readable and maintainable if their special variables are given a distinct prefix. For example, naming each parameter in a function's parameter list with a leading "p" or "p_" makes their special nature easy to discern at a glance, especially when a function has several dozen local variables competing for your attention. Similarly, the prefix "r" or "r_" could be used for ByRef parameters, and "s" or "s_" could be used for static variables.

The One True Brace (OTB) style may optionally be used to define functions. For example:

```Add(x, y) {
return x + y
}```

## Using #Include to Share Functions Among Multiple Scripts

The #Include directive may be used (even at the top of a script) to load functions from an external file.

Explanation: When the script's flow of execution encounters a function definition, it jumps over it (using an instantaneous method) and resumes execution at the line after its closing brace. Consequently, execution can never fall into a function from above, nor does the presence of one or more functions at the very top of a script affect the auto-execute section.

## Libraries of Functions: Standard Library and User Library

A script may call a function in an external file without having to use #Include. For this to work, a file of the same name as the function must exist in one of the following library directories:

```A_ScriptDir "\Lib\"  ; Local library.
A_MyDocuments "\AutoHotkey\Lib\"  ; User library.
"path-to-the-currently-running-AutoHotkey.exe\Lib\"  ; Standard library.```

For example, if a script calls a nonexistent function `MyFunc()`, the program searches for a file named "MyFunc.ahk" in the user library. If not found there, it searches for it in the standard library. If a match is still not found and the function's name contains an underscore (e.g. `MyPrefix_MyFunc`), the program searches both libraries for a file named `MyPrefix.ahk` and loads it if it exists. This allows `MyPrefix.ahk` to contain both the function `MyPrefix_MyFunc` and other related functions whose names start with `MyPrefix_`.

The local library is searched before the user library and standard library.

Only a direct function call such as `MyFunc()` can cause a library to be auto-included. If the function is only called dynamically or indirectly, such as by a timer or GUI event, the library must be explicitly included in the script. For example: `#Include <MyFunc>`

Although a library file generally contains only a single function of the same name as its filename, it may also contain private functions and subroutines that are called only by it. However, such functions should have fairly distinct names because they will still be in the global namespace; that is, they will be callable from anywhere in the script.

If a library file uses #Include, the working directory for #Include is the library file's own directory. This can be used to create a redirect to a larger library file that contains that function and others related to it.

The script compiler (ahk2exe) also supports library functions. However, it requires that a copy of AutoHotkey.exe exist in the directory above the compiler directory (which is normally the case). If AutoHotkey.exe is absent, the compiler still works but library functions are not automatically included.

Functions included from a library perform just as well as other functions because they are pre-loaded before the script begins executing.

## Built-in Functions

Any optional parameters at the end of a built-in function's parameter list may be completely omitted. For example, `WinExist("Untitled - Notepad")` is valid because its other three parameters would be considered blank.

A built-in function is overridden if the script defines its own function of the same name. For example, a script could have its own custom WinExist function that is called instead of the standard one. However, the script would then have no way to call the original function.

External functions that reside in DLL files may be called with DllCall.

To get more details about a particular built-in function below, simply click on its name.

### Frequently-used Functions

Function Description
DirExist Checks for the existence of a folder and returns its attributes.
FileExist Checks for the existence of a file or folder and returns its attributes.
GetKeyState Returns true (1) if the specified key is down and false (0) if it is up.
InStr Searches for a given occurrence of a string, from the left or the right.
RegExMatch Determines whether a string contains a pattern (regular expression).
RegExReplace Replaces occurrences of a pattern (regular expression) inside a string.
StrLen Retrieves the count of how many characters are in a string.
StrReplace Replaces occurrences of the specified substring with a new string.
StrSplit Separates a string into an array of substrings using the specified delimiters.
SubStr Retrieves one or more characters from the specified position in a string.
WinActive Checks if the specified window exists and is currently active (foremost), and returns its Unique ID (HWND).
WinExist Checks if a matching window exists and returns the Unique ID (HWND) of the first matching window.

### Miscellaneous Functions

Function Description
CallbackCreate Creates a machine-code address that when called, redirects the call to a function in the script.
Chr Returns the string (usually a single character) corresponding to the character code indicated by the specified number.
DllCall Calls a function inside a DLL, such as a standard Windows API function.
Exception Creates an object which can be used to throw a custom exception.
FileOpen Provides object-oriented file I/O.
Format Formats a variable number of input values according to a format string.
Func Retrieves a reference to the specified function.
GetKeyName/VK/SC Retrieves the name/text, virtual key code or scan code of a key.
IsByRef Returns a non-zero number if a ByRef parameter of a function was supplied with the specified variable.
IsFunc Returns a non-zero number if the specified function exists in the script.
IsLabel Returns a non-zero number if the specified label exists in the script.
IsObject Returns a non-zero number if the specified value is an object.
ListView Functions to add, insert, modify or delete ListView rows/colums, or to get data from them.
NumGet Returns the binary number stored at the specified address+offset.
NumPut Stores a number in binary format at the specified address+offset.
OnMessage Monitors a message/event.
Ord Returns the ordinal value (numeric character code) of the first character in the specified string.
StrGet Copies a string from a memory address, optionally converting it between code pages.
StrPut Copies a string to a memory address, optionally converting it between code pages.
TreeView Functions to add, modify or delete TreeView items, or to get data from them.
Trim Trims characters from the beginning and/or end of a string.
VarSetCapacity Enlarges a variable's holding capacity or frees its memory.

### Math

Function Description
Abs Returns the absolute value of Number.
Ceil Returns Number rounded up to the nearest integer (without any .00 suffix).
Exp Returns e (which is approximately 2.71828182845905) raised to the Nth power.
Floor Returns Number rounded down to the nearest integer (without any .00 suffix).
Log Returns the logarithm (base 10) of Number.
Ln Returns the natural logarithm (base e) of Number.
Max / Min Returns the highest/lowest value of one or more numbers.
Mod Returns the remainder when Dividend is divided by Divisor.
Round Returns Number rounded to N decimal places.
Sqrt Returns the square root of Number.
Sin / Cos / Tan Returns the trigonometric sine/cosine/tangent of Number.
ASin / ACos / ATan Returns the arcsine/arccosine/arctangent in radians.