作者: Hiroshi Shinohara
日時: 2003/11/03(12:25)
  Co-Expressionの続きです。前回は Co-Expressionを使って、generatorの出力を
全部書き出しました。 するとこの Co-Expressionは出力を出し尽くして、その後は
何も出力しません。
  でも、実際のプログラムでは、generatorの出力を書き出すのが目的ではなくて、
generatorを何かの処理に使うが、中間データとして generatorの出力も書き出して
おきたい。 中間データと最終データと比較するために、一時的に出力するケースが
殆どだと思います。
  そういう時もう1回 Co-Expressionを使うために、Co-Expressionをリフレッシュ
出来ます。正確には、Co-Expressionのコピーを生成するとのことですが。
  Cが Co-Expressionとして、^Cと記すと Cのリフレッシュ(コピー)が生成されます。
  C := ^C とすると、Cをまた最初から使えます。

  この辺を試してみましょう。
-----^ CEXP05.ICN ( date:03-11-03 time:10:51 ) -------------<cut here
####################
# Co-Expression 5
####################
# Cexp05.icn Rev.1.1 2003/11/03 風つかい
# Co-Expressionのリフレッシュ
# This file is in the public domain.

procedure main()
  write("Co-Expression テスト5")

  # Co-Expressionの生成。
  C1 := create(seq() \10)       # Co-Expressionの生成 1 〜 10 を生成
  write("seq() \\10 を書き出し")
  write(gen_out(C1))            # generator出力の書き出し

  write("\nリフレッシュ版を書き出し")
  write(gen_out(^C1))

  C1 := ^C1                     # C1リフレッシュ
  write("\n途中まで書き出してリフレッシュ")
  write("C1を 3個書き出し")
  write(@C1)
  write(@C1)
  write(@C1)
  write("C2 := ^C1 リフレッシュ版として C2を生成")
  C2 := ^C1
  write("C2を 2個書き出し")
  write(@C2)
  write(@C2)
  write("C1の残りを書き出し")
  write(gen_out(C1))
  write("C2の残りを書き出し")
  write(gen_out(C2))

end

####################
# generatorの一行書き出し procedure
####################
procedure gen_out(C,s)
  /s := " "               # 間隔文字
  s1 := ""                # 足し込み用 空文字列
  while s_cex := @C do {  # Co-Expressionから順に取り出して
    s1 ||:= s_cex || s    # 足し込む
  }
  return s1[1:-*s]
end
-----$ CEXP05.ICN ( lines:47 words:110 ) -------------------<cut here

  動かすとこうなります。
-----^ CEXP05.1 ( date:03-11-03 time:10:51 ) ---------------<cut here
Co-Expression テスト5
seq() \10 を書き出し
1 2 3 4 5 6 7 8 9 10

リフレッシュ版を書き出し
1 2 3 4 5 6 7 8 9 10

途中まで書き出してリフレッシュ
C1を 3個書き出し
1
2
3
C2 := ^C1 リフレッシュ版として C2を生成
C2を 2個書き出し
1
2
C1の残りを書き出し
4 5 6 7 8 9 10
C2の残りを書き出し
3 4 5 6 7 8 9 10
-----$ CEXP05.1 ( lines:20 words:58 ) ----------------------<cut here

  複数の Co-Expressionは独立に使えますので、次のように2つの Co-Expressionを
並列して使えます。  数発生と順列発生を並行して動かす例を。
-----^ CEXP06.ICN ( date:03-11-03 time:11:43 ) -------------<cut here
####################
# Co-Expression 6
####################
# Cexp06.icn Rev.1.1 2003/11/03 風つかい
# Co-Expressionの並列使用
link msperm            # 順列生成 generator       # 秋の夜長は Iconでも(3)

procedure main()
  write("Co-Expression テスト6")
  # Co-Expression1
  Seq    := create right(seq() \10,2)               # 数発生 1〜10 桁合わせつき
  # Co-Expression2                      # ↓数発生 1,2
  Msperm := create right(msperm("ABCDE",1 to 2),2)  # 順列発生     桁合わせつき
                       # ↑順列発生generator
  while write(@Seq," ",@Msperm)         # 書き出し

end
-----$ CEXP06.ICN ( lines:17 words:57 ) --------------------<cut here

  結果はこうなります。
-----^ CEXP06.1 ( date:03-11-03 time:11:43 ) ---------------<cut here
Co-Expression テスト6
 1  A
 2  B
 3  C
 4  D
 5  E
 6 AA
 7 AB
 8 AC
 9 AD
10 AE
-----$ CEXP06.1 ( lines:11 words:22 ) ----------------------<cut here

  Co-Expressionから順次データが生成できますが、ある時点までに生成したデータの
数を知ることができます。 Cが Co-Expressionとして、*Cで生成した数が分かります。

  これを使うと前のプログラムは、こう書けます。
-----^ CEXP07.ICN ( date:03-11-03 time:11:42 ) -------------<cut here
####################
# Co-Expression 7
####################
# Cexp07.icn Rev.1.1 2003/11/03 風つかい
# Co-Expressionの生成数
link msperm            # 順列生成 generator       # 秋の夜長は Iconでも(3)

procedure main()
  write("Co-Expression テスト7")
                                        # ↓数発生 1,2
  Msperm := create right(msperm("ABCDE",1 to 2) \10,2) # 順列発生 桁合わせつき
                       # ↑順列発生generator     ↑10個限定
  while s := @Msperm do write(right(*Msperm,2)," ",s)  # 書き出し
                                  # ↑Mspermの生成数
end
-----$ CEXP07.ICN ( lines:15 words:52 ) --------------------<cut here

  Co-Expression自体は generatorでないため、他のフィルター procedureと組合せる
るために、Co-Expression -> generator変換 のための procedureを作ってみました。
  これを使って、エクセル風列番号を書き出すプログラムの例を。
-----^ CEXP08.ICN ( date:03-11-03 time:12:06 ) -------------<cut here
####################
# Co-Expression 8
####################
# Cexp08.icn Rev.1.1 2003/11/03 風つかい
# Co-Expression -> Generatorのテスト
link msperm,           # 順列生成 generator       # 秋の夜長は Iconでも(3)
     lineg             # 一行整形 generator       # 秋の夜長は Iconでも(5)

procedure main()
  write("Co-Expression テスト8")
  Msperm := create msperm(&ucase,1 to 2)
  write("C2g  テスト")
  every s := lineg(,,right(C2g(Msperm),2) \66 | &null) do write(s)

  write("\nC2gn テスト")
  Msperm := ^Msperm
  every s := lineg(,,right((r := C2gn(Msperm) \66).no,2) || ":" ||
                     right(r.data,2) | &null,10) do write(s)

end


####################
# Co-Expression -> generator
####################

# Co-Expression -> generator
procedure C2g(C)
  while x := @C do suspend x
end

# Co-Expression/生成数 -> generator
record rec_C2gn(data,no)
procedure C2gn(C)
  while x := @C do suspend rec_C2gn(x,*C)
end
-----$ CEXP08.ICN ( lines:36 words:107 ) -------------------<cut here

  動かすとこうなります。
-----^ CEXP08.1 ( date:03-11-03 time:12:06 ) ---------------<cut here
Co-Expression テスト8
C2g  テスト
 A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ AR AS AT AU AV AW AX AY AZ
BA BB BC BD BE BF BG BH BI BJ BK BL BM BN

C2gn テスト
 1: A  2: B  3: C  4: D  5: E  6: F  7: G  8: H  9: I 10: J 11: K 12: L 13: M
14: N 15: O 16: P 17: Q 18: R 19: S 20: T 21: U 22: V 23: W 24: X 25: Y 26: Z
27:AA 28:AB 29:AC 30:AD 31:AE 32:AF 33:AG 34:AH 35:AI 36:AJ 37:AK 38:AL 39:AM
40:AN 41:AO 42:AP 43:AQ 44:AR 45:AS 46:AT 47:AU 48:AV 49:AW 50:AX 51:AY 52:AZ
53:BA 54:BB 55:BC 56:BD 57:BE 58:BF 59:BG 60:BH 61:BI 62:BJ 63:BK 64:BL 65:BM
66:BN
-----$ CEXP08.1 ( lines:13 words:164 ) ---------------------<cut here

風つかい(hshinoh@...)
IconのWWWは、  http://www.cs.arizona.edu/icon/
UniconのWWWは、http://unicon.sourceforge.net/index.html
BGM: Country Dream / 杉本喜代志