Think Stitch
PRINCIPIA  最近の更新


逐次合成の利用2例

逐次合成 seq を利用する例を2つご紹介します。

プロセスの再利用

逐次合成 seq を使うと、関数、手続き、あるいはサブルーチンのようにプロセスを再利用することができます。

例えば、プロセス P は処理の途中で何度か3つのプロセス Q, R, S に通知を出す必要があるとします。各プロセスとの接続チャネルを chq, chr, chs とすると、プロセス P の定義は次のようなものになるでしょう。

(define-process P
  処理1
  (! chq (notif1)
     (! chr (notif1)
        (! chs (notif1)
           処理2
           (! chq (notif2)
              (! chr (notif2)
                 (! chs (notif2)
                    処理3)))))))

これはおよそ良い記述とはいえません。通知がまとまっていない上に、同じ構造のコードが繰り返されているからです。通知を行うプロセス NOTIF と逐次合成 seq を使うと、上記のプロセスを次のように記述することができます。

(define-process (NOTIF n)
  (! chq (n)
     (! chr (n)
        (! chs (n)
           SKIP))))

(define-process P
  (seq
    処理1'
    (NOTIF notif1)
    処理2'
    (NOTIF notif2)
    処理3))

ここで、処理1', 処理2' は処理1, 処理2の末尾をそれぞれ SKIP にしたものです。これは seq で次のプロセスに移行できるようにするためです。

分岐の合流

条件分岐 if を使って処理を分けたとき、それぞれ固有の処理を行った後の処理が再び同じものになることがよくあります。別のいい方をすると、分岐後再び合流したいということです。

合流しないでプロセスを記述すると、同じ記述を2度書くことになります。

(define-process (P x)
  (if (pred x)
      (! a (? c (x) (! d (x) Q)))
      (! b (? c (x) (! d (x) Q))) ))

これを解決する1つの方法は、名前のついた補助プロセスを定義することです。

(define-process (P x)
  (if (pred x)
      (! a (P2 x))
      (! b (P2 x))))

(define-process (P2 x)
  (? c (y) (! d (x y) Q)))

しかしこの程度であれば、わざわざプロセスを定義するのはやや大げさです。このような場合には逐次合成 seq を使うと次のように書くことができます。

(define-process (P x)
  (seq
    (if (pred x)
        (! a SKIP)
        (! b SKIP))
    (? c (y) (! d (x y) Q))))
2013/07/31
© 2013,2014,2015 PRINCIPIA Limited