分岐ステートメントの GoSub と On...GoSub は、使い方の限られたプログラミングテクニックです。同一プロシージャ内の任意の位置 (複数可) から制御を移すことにより、ステートメントグループを実行できます。機能的にはステートメントはサブルーチンのように動作しますが、引数をとることや、別のスコープの設定はできず、他のプロシージャやスクリプトから使用できません。通常のサブルーチンとしてステートメントを記述するほうがより一般的であり、便利です。
構文は次のとおりです。
GoSub label
On expression GoSub label [ , label ]...
Return
ステートメント GoSub label はラベル label の付いたステートメントに制御を移し、label で始まるステートメントから実行を開始し、次のどれかが発生するまで実行を続けます。
GoSub ステートメントの次のステートメントに制御が戻る
スクリプトの実行が終わる (End ステートメント)、または中に含むプロシージャの実行が終了する (その他のステートメントの 1 つ)
ラベル付きステートメントの後で Return ステートメントの前に実行されるステートメントグループは、その他の制御の移動も含めて、現在のプロシージャ内のサブルーチンとして動作します。
ステートメント On expression GoSub label, label, ... も GoSub label と同様に制御を移しますが、ジャンプ先のラベルが expression の値に基づいて決まる点が異なります。つまり、expression が 1 であれば最初の label へ、expression が 2 であれば、2 番目の label へ、というように制御が移ります。 (これらのラベルが同じであっても構いません)。Return ステートメントは On...GoSub の次のステートメントに制御を戻します。
プロシージャ内の GoSub ステートメントの位置は、制御が移される先のラベル付きステートメントの位置とは関係ありません。必要なのは、GoSub とそのジャンプ先のラベル付きステートメントが同一プロシージャ内に存在する必要がある、ということのみです。実際の制御のフローは実行時に決まります。
GoSub または On...GoSub ステートメントを実行すると、戻り位置が定義されます。Return ステートメントが実行される前に別の GoSub または On...GoSub が実行されることもあります。Return ステートメントが実行されると、最後に定義された戻り位置に制御が戻されます。その後、その戻り位置の定義は解除されます。
Return ステートメントはプロシージャからは戻りません。プロシージャ内に現在戻り位置がない場合に Return ステートメントを実行しようとすると、ランタイムエラーになります。
これらのステートメントは、戻り点位置を設定しないで制御を移す GoTo や On...GoTo ステートメントとは異なります。
次の例では、On...GoSub を使用して、LotusScript® 言語の 2 つの単純なパフォーマンステストのどちらかを実行します。入力ボックスに 1 か 2 を入力することにより、Do ループの 1000 回繰り返しの時間測定と、1 秒間に実行される Yield ステートメント数のカウントのどちらかをユーザーが選択します。スクリプトは On...GoSub を使用して選択されたテストへ分岐して実行します。1 つの Print ステートメントで結果を表示します。
Sub RunPerfTest
Dim directTempV As Variant, directTest As Integer, i As Integer
Dim startTime As Single, measure As Single, idPace As String
SpecTest: directTempV = InputBox$ _
(|Type 1 for iteration time, or 2 for # of yields:|)
If Not IsNumeric(directTempV) Then Exit Sub
directTest% = CInt(directTempV)
If directTest% < 1 Or directTest% > 2 Then _
Beep : GoTo SpecTest
i% = 0
' Branch on 1 or 2.
On directTest% GoSub TimeCheck, ItersCheck
' Return here to print the performance-test result,
' and leave.
Print idPace$ measure!
Exit Sub
TimeCheck:
startTime! = Timer()
Do While i% <= 1000
i% = i% + 1
Loop
measure! = Timer() - startTime!
idPace$ = "Time in seconds for 1000 Do iterations: "
Return
ItersCheck:
startTime! = Timer()
Do While Timer() < startTime! + 1
Yield
i% = i% + 1
Loop
measure! = i%
idPace$ = "Number of Yields in 1 second: "
Return
End Sub
Call RunPerfTest()