Concurrent Clean : コンパイラがこける

file :: !Int -> *File
file 1 = code {
           push_b 0
       }

上の関数定義を作ると、次のエラーになってコンパイラがこける

Run-time error! Program evaluated undefined value?!clm: reading compiler result failed: No such file or directory

また、次のようなのは、コンパイラが空のabcファイルを作成する。

f a = code inline {}

Concurrent Clean : 参照型

というわけで、参照型を作ってみた。Cleanでは配列を破壊的に更新できるという特徴を生かして、マジックプログラミングしました。

::*Ref a

reference :: !.a -> *(Ref .a)
copy :: !*(Ref .a) -> (!*(Ref .a), !*(Ref .a))
apply :: !(.a -> .a) !*(Ref .a) -> *(Ref .a)
access :: !(.a -> (.b,.a)) !*(Ref .a) -> (!.b, !*(Ref .a))

とりあえず、上のような関数セットを用意して、

Start w
    # ri = reference 1
      (ri1,ri2) = copy ri
      ls1 = process 1 ri1
      ls2 = process 2 ri2
      ls = interleave ls1 ls2
    = take 10 ls

process a ri
    # (e,ri) = access f ri
    = [e:process a ri]
  where
    f i = (i,i+a)

interleave [a:aa] bb
    = [a:interleave bb aa]

のようなプログラムが、

[1,2,4,5,7,8,10,11,13,14]

のような出力になります。
特徴は、

  • 参照型の値は、字句上の順に更新されるのではなく、実行時の順に交信される
  • 参照型は共有はできないが、コピーはできる
  • 参照型へのアクセスは、一意型によって意味的に安全にアクセスできる

Concurrent Clean : Re: ハンドルから実体を取り出す

[id:lethevert:20070425:p3]だけれど間違ってる。
リポジトリを使うという方法は関数的でないところが問題ではなくて(一意型を使えば、関数的に扱えるから)、型付けの問題と安全性の問題が引っかかっているのと、リポジトリサービスそのものをCleanでどう実装するかという問題に気持ち悪さを感じるから。

      • -

で、あの後思い付いたのだけれど、参照型を導入することで、この問題が解決するかもしれない。一意型を利用した純粋関数的な参照型のイメージを思い付いて、それは現行のABCマシンで実装できそうな気がする。