For-회돌이 [AHK_L 59+]

일련의 명령어를 객체 안의 각 키-값 쌍마다 한 번씩 반복합니다.

For Key , Value in Expression

매개변수

Key

각 반복을 시작할 때 키를 저장할 변수의 이름.

Value

현재 키에 연관된 값을 저장할 변수의 이름.

Expression

객체 또는 객체를 담고 있는 변수로 결과가 되는 표현식.

논평

Expression은 회돌이가 시작되기 전에 한 번만 평가됩니다. 그의 결과가 객체가 아니면, 실행은 즉시 회돌이 몸체 다음 줄로 점프합니다; 그렇지 않으면, 열거(enumerator) 객체를 열람하기 위하여 그 객체의 _NewEnum() 메쏘드가 호출됩니다. 각 반복을 시작할 때, 그 열거 객체의 Next() 메쏘드를 사용하여 다음 키-값 쌍을 열람합니다. Next()가 0 또는 빈 문자열을 돌려주면, 회돌이가 끝납니다.

for-회돌이와 정확하게 동등하지는 않지만, 다음 예제는 이 처리 과정을 시연합니다:

_enum := (Expression)._NewEnum()
if IsObject(_enum)
    while _enum.Next(Key, Value)
    {
        ...
    }

기존의 키-값 쌍은 회돌이 중에 변경할 수 있지만, 그러나 키를 삽입하거나 제거하면 항목을 빼먹거나 여러 번 반복하는 문제를 야기할 수 있습니다. 한 가지 우회책은 제거할 키 목록을 만든 다음, 첫 번째 회돌이가 완료된 후 두 번째 회돌이를 사용하여 키를 제거하는 것입니다. Object.Remove(first, last)를 사용해 회돌이 없이 한 범위의 키를 제거할 수 있다는 것에 주목하십시오.

for-회돌이는 보통 다음에 블록이 따라옵니다. 이 블록은 회돌이의 몸체를 형성하는 서술문의 집단입니다. 그렇지만, 서술문이 하나만 있는 회돌이는 블록을 요구하지 않습니다 ("if" 그리고 그의 "else"는 이런 목적으로 하나의 서술문으로 계수됩니다). One True Brace (OTB) 스타일을 선택적으로 사용할 수 있습니다. 이 스타일은 여는 활괄호를 그 아래가 아니라 같은 줄에 나타나도록 허용합니다. 예를 들어: for x, y in z {.

모든 회돌이와 마찬가지로, Break, Continue 그리고 A_Index를 사용할 수 있습니다.

COM 객체

키(Key)와 값(Value)은 열거자의 Next() 메쏘드에 직접 건네집니다. 거기에 할당되는 값은 어떤 종류의 객체가 열거되고 있는가에 따라 다릅니다. COM 객체라면, Key에는 IEnumVARIANT::Next()가 돌려주는 값이 담기고 Value에는 그의 variant 유형을 가리키는 번호가 담깁니다. 예를 들어, Scripting.Dictionary 객체와 사용될 때, 각 Key는 사전으로부터 온 키가 담기고 Value는 전형적으로 문자열에 8, 정수에 3이 담깁니다. 유형 코드 목록은 ComObjType()를 참조하십시오.

[v1.0.96.00+]: SafeArray를 열거할 때, Key에는 현재 원소가 담기고 Value에는 그의 variant 유형이 담깁니다.

Enumerator object, Object._NewEnum(), While-loop, Loop, Until, Break, Continue, Blocks

예제

객체의 키-값 쌍을 나열합니다.

colours := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)
; 위의 표현식은 아래의 "colours" 대신에 직접 사용할 수 없습니다:
for k, v in colours
    s .= k "=" v "`n"
MsgBox % s

Lists all open Explorer and Internet Explorer windows, using the Shell object.

for window in ComObjCreate("Shell.Application").Windows
    windows .= window.LocationName " :: " window.LocationURL "`n"
MsgBox % windows

Class: CEnumerator

Provides a generic enumerator object that can be used for iterating over numeric keys. 배열은 반복 중에 변경해서는 안됩니다. 그렇지 않으면, 반복 범위가 유효하지 않게 됩니다. 배열 경계에 대하여 맞춤 MaxIndex() 함수를 정의할 수 있습니다. 1과 최대 인덱스 사이에 빠진 원소가 있다면, 반복되기는 하지만 값은 ""가 됩니다. 이것은 진짜 희소 행열은 이 열거 객체가 설계상 지원되지 않는다는 뜻입니다. Source: Suggestions on documentation improvements

/*
Class: CEnumerator

객체가 이 반복자를 사용하게 만들려면, 다음 함수를 클래스 정의에 삽입하십시오:

    _NewEnum()
    {
    	return new CEnumerator(this)
    }
*/

; 열거 객체를 반복합니다
For k, v in Test
    MsgBox %k%=%v%

; 사용법을 시연하기 위해 클래스를 테스트합니다
class Test
{
    static Data := ["abc", "def", "ghi"]

    _NewEnum()
    {
        return new CEnumerator(this.Data)
    }
}

class CEnumerator
{
    __New(Object)
    {
        this.Object := Object
        this.first := true
        ; 속도를 위해 캐쉬합니다. 맞춤 MaxIndex() 함수가 수행성능이 좋지 않을 경우 유용합니다.
        ; 그 응답은 반복 동안에 키-값 쌍이 삽입되지 않는다는 뜻입니다. 그렇지 않으면 범위가 무효가 되어 버릴 것입니다.
        this.ObjMaxIndex := Object.MaxIndex()
    }

    Next(ByRef key, ByRef value)
    {
        if (this.first)
        {
            this.Remove("first")
            key := 1
        }
        else
            key ++
        if (key <= this.ObjMaxIndex)
            value := this.Object[key]
        else
            key := ""
        return key != ""
    }
}