リストと配列の ForAll ループ

繰り返しブロックステートメント ForAll は、ステートメントのブロックを配列またはリストの各要素に対して 1 回ずつ、繰り返し実行します。

構文は次のとおりです。

ForAll refVar In container

statements

End ForAll

container は、既存の配列またはリストに名前を付けたものです。

ForAll ステートメントの本体にあるステートメントが container の最後の要素に対して実行された後、実行は ForAll ステートメントに続く次のステートメントから続行されます。しかし、実行中に GoTo、GoSub、Exit、End などを介して ForAll ステートメントの本体の外に制御が渡された場合、実行がこれ以外の場所で続くこともあります。

statements の連続した繰り返しで、参照変数 refVarcontainer の各要素をそれぞれ参照します。名前 refVar は、これが ForAll ステートメントで現れた時点で宣言されます。これは、コンテナ名自身の同義語ではありませんが、コンテナの個々の要素の別名です。それぞれの繰り返しで、そのデータ型は、コンテナの要素のデータ型になります。

以下に例を示します。

Dim persStats List As String     ' Declare list of type String.
persStats("Name") = "Ian"        ' Assign list elements.
persStats("Age") = "36"
persStats("Home state") = "MD"
ForAll idAttrib In persStats    
   Print ListTag(idAttrib)": " idAttrib 
    ' For each item in persStats, print its tag and value.
End ForAll
' Output:
' Name: Ian
' Age: 36
' Home state: MD

次の例は、コンテナがリストでなく配列である ForAll ステートメントを示します。

Dim numberId(2) As Integer      
For i% = 0 To 2
   numberId(i%) = i% + 1
Next
ForAll p2 In numberId
   Print TypeName(p2) p2 * p2
     ' Print the type and the square of the number
     ' in each element.
End ForAll
' Output:
' INTEGER 1
' INTEGER 4
' INTEGER 9

配列またはリストに要素がない場合、その配列またはリストをコンテナ変数に持つ ForAll ステートメントは効果がありません。

以下に例を示します。

Dim testNone() As Integer
Print "Before ";
ForAll iTest In testNone
   Print iTest, "In ForAll ";
End ForAll
Print "After"
' Output:
' Before After

参照変数のスコープ

ForAll ステートメントの外の参照変数は参照できません。

以下に例を示します。

ForAll p2 In numberId
   Print p2 * p2 ;
End ForAll
Print
Print TypeName(p2)
' Output:
' 1  4  9
' Error 115: Illegal reference to FORALL alias variable: P2

ForAll ステートメントの外の参照変数は宣言できません。

以下に例を示します。

Dim p2 As Integer
ForAll p2 In numberId
   Print p2 * p2 ;
End ForAll
' Output:
' Error 164: FORALL alias variable was previously declared: P2

しかし、1 つの ForAll ステートメントの参照変数を別の ForAll ステートメントの参照変数として再利用することはできます。2 番目の ForAll ステートメントのコンテナ変数は、最初の ForAll ステートメントのコンテナ変数と同じデータ型でなければなりません。データ型が異なる場合、LotusScript® コンパイラはエラーを生成します(コンテナは配列またはリストです)。

以下に例を示します。

ForAll p2 In numberId
   Print p2 * p2 ;
End ForAll
Print
Dim numShiftV(3) As Variant
ForAll p2 In numShiftV
   p2 = 1
End ForAll
' Output:
' 1  4  9
' Error 114: FORALL alias variable is not of same data type: P2

この例では、次のように p2 はステートメントによって暗黙的に Integer 型の変数として宣言されました。

ForAll p2 In numberId

したがって、次のステートメントで試みるように Variant 型の変数として再度宣言することはできません。

ForAll p2 in numShiftV

宣言された numShiftV のデータ型を Integer 型に変更すれば、p2 の 2 度目の使用が有効になります。

コンテナ変数の要素を変更する

次の例は、ForAll ステートメントがコンテナ配列またはリストの各要素の現在値を参照する方法を示します。ForAll ステートメント内のステートメントは、コンテナ配列 iHold の 2 つの要素の現在値を変更します。新しい値は、ForAll ステートメントの最初の繰り返し内の後続のステートメントによって使用され、iHold の次の要素に対して ForAll ステートメントが実行される際にも使用されます。

Dim iHold(1) As Integer
iHold(0) = 50
iHold(1) = 100
ForAll iElem In iHold
   ' Print the values of iElem and iHold(1)
   ' upon each entry into ForAll.
   Print
   Print "iElem and iHold(1) IN:" iElem iHold(1)
   ' Add 2 to the current element. The current element is
   ' iHold(0) the first time through ForAll, and iHold(1)
   ' the second time through.
   iElem = iElem + 2
   ' Increment the value of iHold(1) by 5 (both trips through).
   iHold(1) = iHold(1) + 5
   ' Print the current values of iElem and iHold(1)
   ' upon each exit from ForAll.
   Print "iElem and iHold(1) OUT:" iElem iHold(1)
End ForAll
' Output:
' iElem and iHold(1) IN:  50  100
' iElem and iHold(1) OUT: 52  105
' iElem and iHold(1) IN: 105  105
' iElem and iHold(1) OUT:112  112

With ステートメントが同じタスクをどのように実行できるかを比較するには、「ユーザー定義のデータ型とクラス」で With ステートメントの説明を参照してください。

次の例では、コンテナ配列 cHold の要素の値は、クラス refClass のオブジェクトへの参照です。最初、cHold の 2 つの要素は異なるオブジェクト参照を含んでいます。ForAll ステートメントの最初の繰り返しで、最初の要素の値は 2 番目の値にリセットされます。その後は、要素は同じオブジェクトを参照します。

Option Base 1
Class refClass
   Public cVar As Integer
End Class
Dim cHold(2) As refClass
Set cHold(1) = New refClass
Set cHold(2) = New refClass
' The output from the following Print statement
' shows that cHold(1) and cHold(2) hold different 
' objects references.
If cHold(1) Is cHold(2) _
   Then Print "Same object" Else Print "Different objects"
cHold(1).cVar% = 100
cHold(2).cVar% = 200
ForAll cElem In cHold
   Print
   Print cElem.cVar%
   Set cHold(1) = cHold(2)
   ' Now cHold(1) holds the same reference as cHold(2), so 
   ' cElem refers to that object in the following statements
   ' (on both trips through ForAll).
   Print cElem.cVar%
   If cHold(1) Is cHold(2) _
      Then Print "Same object" Else Print "Different objects"
End ForAll
' Output:
' Different objects
'
' 100
' 200
' Same object
'
' 200
' 200
' Same object

上記の 2 つの例は、ForAll ステートメントのコンテナ配列の内容を変更しますが、構造は変更しません。コンテナまたはコンテナ要素に Erase ステートメントを使用するか、配列に ReDim ステートメントを使用することはできますが、結果が予想できないためお勧めしません。

同様に、ForAll ステートメントの外から、内部のラベルの付いたステートメントに制御を移すことができますが、これもお勧めしません。この理由は、外から内部に制御を移すと、ForAll ステートメントが特定の要素に対する実行を開始する際に ForAll 参照変数の初期化が発生するよう組み込まれていても、これが省かれるためです。

要素のアクセス順序

最初の例で示されるように、リストコンテナに対する ForAll ステートメントは、リスト内で要素が保持されている順序に従ってリスト要素にアクセスします。配列に対する ForAll ステートメントは、LotusScript によって格納された順序で配列要素にアクセスします。1 次元の配列 arrA では、arrA(0)、arrA(1)、arrA(2)、... の順になります (0 が arrA の最小の添え字である場合)。LotusScript では、多次元配列は「先入れ先変更」(配列の添え字リストの先頭の添え字が最初に変更されます) で格納されます。ForAll ステートメントは、これと同じ順序で配列要素にアクセスします。

以下に例を示します。

Option Base 1g5
Dim eyeJay(2,3) As String
' Access the elements of eyeJay in "last fastest" order
' for assignment and printing.
For i% = 1 To 2
   For j% = 1 To 3
      ' In eyeJay(i,j), store the string "(i,j)".
      eyeJay(i%, j%) = "(" & Str(i%) & "," & Str(j%) & ")"
      ' Print the element value.
      Print eyeJay(i%, j%),
Next j%, i%
Print
' Now print the elements of eyeJay one at a time in the 
' same order as the ForAll statement accesses them.
' This order is first fastest, the storage order for any array.
Print
ForAll elem In eyeJay
   Print elem,
End ForAll
' Output:  
' ( 1, 1)  ( 1, 2)   ( 1, 3)   ( 2, 1)   ( 2, 2)   ( 2, 3)
' ( 1, 1)  ( 2, 1)   ( 1, 2)   ( 2, 2)   ( 1, 3)   ( 2, 3)