Concurrent Clean : share file

share fileといっても、プロセス間共有するという話ではない。
Cleanでファイルを取り扱うときは、通常、一意性型属性付きで取り扱うのだが、一意性型属性なしで取り扱うこともできるのだ。ただし、読取専用で、一度オープンするとクローズする方法はない。標準入力は使えない。・・・あまり使い道が思い浮かばないのだけど。

Start w # (_,f,w) = sfopen "num.txt" FReadText w  // share fileをオープン
          n = fn [0..10] f
          f = fwritei n stderr
          (_,w) = fclose f w
        = w

fn :: ![Int] !File -> Int
fn ls f = sum2 0 ls
  where
    sum2 a [] = a
    sum2 a [x:xr] # (_,i,_) = sfreadi f  // share fileから読み取り
                  = sum2 (a+x+i) xr

num.txtは次の通り。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

結果は「11」になります。ということは、読み取りカーソルが動いていないということですね。カーソルを移動させるには、sfreadiの返値のfを受け渡さないとダメなのかな。

Concurrent Clean : Clean入門

この先の構成。あと4ページ。一意配列と一意性の伝播は触れないことにしました。

  1. 環境構築
  2. プロジェクト
  3. 基本データ型
  4. 基本関数
  5. 関数の作成
  6. ローカルスコープ
  7. 高階関数
  8. クロージャ・カリー化
  9. 無名関数
  10. 演算子
  11. 内包表記
  12. 多相性・型クラス
  13. 型推論
  14. 評価戦略
  15. 正格性
  16. 正格データ構造
  17. マクロ
  18. 定グラフ
  19. 副作用と一意性 <-- ここまで完了
  20. ファイル入出力
  21. 流れとリスト
  22. モジュール
  23. デバッグ

Haskell本

作者の方、出版社の方、これほど普通のプログラマに売れるなんて想定していなかったんじゃないでしょうか?
想像するに、想定読者が、多少は関数型を知っている人くらい(たとえばSchemeないしOCamlは知ってるけど、Haskellは知らないぞとか)になっているのではないかと。読んでないので、ただの想像ですが。
そういう想定の本を、普通のプログラマが読むと、いろいろ不都合が起こりそう。ただの想像ですが。

Algol60 : たらいまわし関数

見つけた。
http://www.csse.monash.edu.au/~lloyd/tildeProgLang/Algol60/
DLしてすぐにサンプルも動いたので、これであれをやってみる。

      • -

やってみました。

'begin'
  'integer' r;

  'integer' 'procedure' tarai(x,y,z);
    'value' x,y,z;
    'integer' x,y,z;
    'begin'
       'if' x <= y 'then'
         tarai := y
       'else'
         tarai := tarai(tarai((x-1), y, z)
                       ,tarai((y-1), z, x)
                       ,tarai((z-1), x, y));
    'end';
  
  r := tarai(10,5,0);
  outstring(1, "tarai(10,5,0) = ");
  outinteger(1, r);
'end'

結果。

$ time a60-v0.20a.exe tarai.a60 
tarai(10,5,0) =  10 
real    0m17.986s
user    0m0.020s
sys     0m0.040s

速くない。なぜかな? やはり、メモ化のせい?

      • -

k.inabaさんより、'value'の指定があると値渡しになってしまうのではという指摘が。
それではということで、コメントアウトして実行してみました。

'begin'
  'integer' r;

  'integer' 'procedure' tarai(x,y,z);
    'COMMENT' 'value' x,y,z;
    'integer' x,y,z;
    'begin'
       'if' x <= y 'then'
         tarai := y
       'else'
         tarai := tarai(tarai((x-1), y, z)
                       ,tarai((y-1), z, x)
                       ,tarai((z-1), x, y));
    'end';
  
  r := tarai(10,5,0);
  outstring(1, "tarai(10,5,0) = ");
  outinteger(1, r);
'end'

結果

$ time a60-v0.20a.exe tarai.a60 
tarai(10,5,0) =  10 
real    0m0.112s
user    0m0.030s
sys     0m0.030s

お、速い!
しかし、数字を大きくするとさすがにだめ。

$ time a60-v0.20a.exe tarai.a60 
tarai(100,50,0) =  100 
real    0m7.921s
user    0m0.030s
sys     0m0.020s

それでは、ということで、xとyだけ値渡しに変更してみる。

  'integer' 'procedure' tarai(x,y,z);
    'value' x,y;
    'integer' x,y,z;

結果はこちら。

$ time a60-v0.20a.exe tarai.a60 
tarai(100,50,0) =  100 
real    0m0.687s
user    0m0.030s
sys     0m0.030s