Next: , Previous: , Up: Control Structures   [Contents][Index]


6.9.5 General control structures with case

Gforth は、 拡張 case を提供することで、 上で説明した複数出口ループの問題を解決する追加のオプションを提供します。 この拡張 case の移植可能な実装は compat/caseext.fs にあります。

この拡張には 3 つの追加ワードがあります。 1 つ目は ?of で、 case 内で(単なる同等性のテストではなく、)一般的なテストが可能です。 例:

: sgn ( n -- -1|0|1 )
  ( n ) case
    dup 0 < ?of drop -1 endof
    dup 0 > ?of drop 1  endof
    \ otherwise leave the 0 on the stack
  0 endcase ;

注意: endcase は値(a value)を drop することに注意してください。 これは of ではほとんどうまいこと機能しますが、 ?of ではたいていうまいこといかないので、 今回も endcase で drop するための値として 0 をスタック置きます。 ここでは、 sgn に渡される n は、 いずれの ?of もトリガーしない場合返り値の 0 そのものになります。

2 番目の追加ワードは next-case で、 これにより case をループに変えることができます。 出口が3つのループは以下のようになります:

case
  condition1 ?of exit-code1 endof
  condition2 ?of exit-code2 endof
  condition3 ?of exit-code3 endof
  ...
next-case
common code afterwards

ご覧のとおり、 これにより、 先程議論したバリエーションの両方の問題が解決されます(see Begin loops with multiple exits)。 注意: endcase とは異なり、 next-case は値をドロップしないことに注意してください。 13

最後の追加ワードは contof です。 これは endof の代わりに使用され、 ループを終了する代わりに次の反復を開始します。 これは、 ダイクストラのガード付きコマンド 繰り返し: do と同様の方法で使用できます。 例:

: gcd ( n1 n2 -- n )
    case
        2dup > ?of tuck - contof
        2dup < ?of over - contof
    endcase ;

ここで、 2 つの ?of はループを継続する異なる方法を持っています。 どちらの ?of もトリガーされない場合、 2 つの数値は等しく、gcd(最大公約数) になります。 Endcase はそれらの 1 つを削除し、もう 1 つは n として残します。

これらのワードを組み合わせることもできます。 以下は、 endcase を除く、 各 case ワードをそれぞれ 1 回使用する例です:

: collatz ( u -- )
    \ print the 3n+1 sequence starting at u until we reach 1
    case
        dup .
        1 of endof
        dup 1 and ?of 3 * 1+ contof
        2/
    next-case ;

この例では、 シーケンスの現在の値をスタックに保持します。 1 の場合、 of がトリガーされ、 値が削除され、 case 構造から去ります。 奇数の場合、 ?of がトリガーされ、 3n+1 が計算され、 contof で次の反復が開始されます。 それ以外の場合、 数値が偶数の場合は 2 で除算され、 next-case でループが再開されます。


Footnotes

(13)

next-case は、 他の case ワード群とは異なり、 名前にハイフン(-)が含まれています。 VFX Forth には値をドロップする nextcase があるので、これと区別するためです。


Next: Arbitrary control structures, Previous: Begin loops with multiple exits, Up: Control Structures   [Contents][Index]