Repeats one or more statements once for each key-value pair in an object.
For Value1, Value2 in Expression
Type: Variable
The variables in which to store the values returned by the enumerator at the beginning of each iteration. The nature of these values is defined by the enumerator, which is determined by Expression. These variables cannot be dynamic.
When the loop breaks or completes, these variables are restored to their former values. If a loop variable is a ByRef parameter, the target variable is unaffected by the loop. Closures which reference the variable (if local) are also unaffected and will see only the value it had outside the loop.
Note: Even if defined inside the loop body, a nested function which refers to a loop variable cannot see or change the current iteration's value. Instead, pass the variable explicitly or bind its value to a parameter.
Up to 19 variables are supported, if supported by the enumerator.
Variables can be omitted. For example, for , value in myMap
calls myMap's enumerator with only its second parameter, omitting its first parameter. If the enumerator is user-defined and the parameter is mandatory, an exception is thrown as usual. The parameter count passed to __Enum is 0 if there are no variables or commas; otherwise it is 1 plus the number of commas present.
Type: Object
An expression which results in an enumerable object, or a variable which contains an enumerable object.
The parameter list can optionally be enclosed in parentheses. For example: for (val in myarray)
The process of enumeration is as follows:
__Enum
method is called to retrieve an enumerator object. If no such method exists, the object itself is assumed to be an enumerator object.Although not exactly equivalent to a for-loop, the following demonstrates this process:
_enum := Expression try _enum := _enum.__Enum(2) while _enum(&Value1, &Value2) { ... }
As in the code above, an exception is thrown if Expression or __Enum yields a value which cannot be called.
While enumerating properties, methods or array elements, it is generally unsafe to insert or remove items of that type. Doing so may cause some items to be skipped or enumerated multiple times. One workaround is to build a list of items to remove, then use a second loop to remove the items after the first loop completes.
A for-loop is usually followed by a block, which is a collection of statements that form the body of the loop. However, a loop with only a single statement does not require a block (an "if" and its "else" count as a single statement for this purpose). The One True Brace (OTB) style may optionally be used, which allows the open-brace to appear on the same line rather than underneath. For example: for x, y in z {
.
As with all loops, Break, Continue and A_Index may be used.
The loop may optionally be followed by an Else statement, which is executed if the loop had zero iterations.
Since Value1 and Value2 are passed directly to the enumerator, the values they are assigned depends on what type of object is being enumerated. For COM objects, Value1 contains the value returned by IEnumVARIANT::Next() and Value2 contains a number which represents its variant type. For example, when used with a Scripting.Dictionary object, each Value1 contains a key from the dictionary and Value2 is typically 8 for strings and 3 for integers. See ComObjType for a list of type codes.
When enumerating a SafeArray, Value1 contains the current element and Value2 contains its variant type.
Enumerator object, OwnProps, While-loop, Loop, Until, Break, Continue, Blocks
Lists the properties owned by an object.
colours := {red: 0xFF0000, blue: 0x0000FF, green: 0x00FF00} ; The above expression could be used directly in place of "colours" below: s := "" for k, v in colours.OwnProps() s .= k "=" v "`n" MsgBox s
Lists all open Explorer and Internet Explorer windows, using the Shell object.
windows := "" for window in ComObject("Shell.Application").Windows windows .= window.LocationName " :: " window.LocationURL "`n" MsgBox windows
Defines an enumerator as a fat arrow function. Returns numbers from the Fibonacci sequence, indefinitely or until stopped.
for n in FibF() if MsgBox("#" A_Index " = " n "`nContinue?",, "y/n") = "No" break FibF() { a := 0, b := 1 return (&n) => ( n := c := b, b += a, a := c, true ) }
Defines an enumerator as a class. Equivalent to the previous example.
for n in FibC() if MsgBox("#" A_Index " = " n "`nContinue?",, "y/n") = "No" break class FibC { a := 0, b := 1 Call(&n) { n := c := this.b, this.b += this.a, this.a := c return true } }