Clean2.4 is available for Windows, Linux and MacOSX!

Clean2.4がリリースされました!>http://wiki.clean.cs.ru.nl/Download_Clean
まさか本当に(MLで言ってた通り) *近々* リリースされるとは. Rinusさんごめんなさいm(_ _)m
(まぁ, MLで言ってたようなマルチコア対応とかDynamicのバックエンドを拡張するとか, 型クラスをDynamicに入れる… みたいな話は入ってないですけど!)

メーリングリストで変更内容がアナウンスされたので,以下でそれを意訳します.

Mac OSX 64bit(x86)に対応

ライセンスが変更された

ランタイムのライセンスがLGPLからSimplified BSDに変更された

import修飾が可能になった

import文で 'qualified' を付けることが出来るようになりました.
'qualified' を付けてimportした識別子はモジュール名(をシングルクォートで囲んだもの)をプレフィックスに付けることで使うことが出来ます.
特殊文字から成る識別子を使う場合は, プレフィックスと識別子の間にスペースを一つ挟む必要があります.

from StdList import drop, ++;
($) infixr 1 :: (a->b) a -> b
($) f a = f a
Start = drop 5 $ [1..3] ++ [1..4]
// [3,4]

にqualifiedを付けると

import StdEnum
from StdList import qualified drop, ++;
Start = 'StdList'.drop 5 $ [1..3] 'StdList'. ++ [1..4]
// [3,4]

とする必要があるようになります.

一意配列の更新(Clean2.3から)

もし同じ関数内で ![] を使うことによる選択と, (同じインデックスによる) 更新を行うことで
一意型の(一意)配列の一意配列を選択して更新することができます.
(選択された要素が使われただけで)配列を使わない事も可能です.

例えば,以下では inc_a により '一意列' が選択され, 更新され, 最後に '配列の列' が更新されます.

 // row_i番目の列の要素をそれぞれ+1する
 inc_row :: !*{#*{#Int}} !Int -> *{#*{#Int}};
 inc_row a row_i
   # (row,a) = a![row_i];
     row = inc_a 0 row;
   = {a & [row_i]=row};

 // 配列の中身をそれぞれ+1する
 inc_a :: !Int !*{#Int} -> *{#Int};
 inc_a i a
   | i<size a
     # (n,a) = a![i];
       a & [i]=n+1;
     = inc_a (i+1) a;
     = a;

型クラスのインスタンスメンバの型に正格性注釈を付与する

型クラスインスタンスのメンバに正格性注釈を付与できます. 例えば

definition module next
class next a where
  next :: a -> a

instance next Int where
  next :: !Int -> Int
  next x = x+1

このようなインスタンスがexportされた場合, インスタンスメンバの型はdefinition moduleに含まれている必要があります.

definition module next
instance next Int
where next :: !Int -> Int

もし正格性注釈が指定されていなければ,

definition module next
instance next Int

このように, 型注釈の無いままexport出来ます.

languare reportが2.1 -> 2.2へアップデートされた

やっと言語レポートがアップデートされました(なぜに2.2なんだ…)
#ちなみに,表紙はversion2.2になっていますが,[preface]のところはバージョンの書き換え忘れてるようですね…


差分はメールに書いて無いですが,とりあえず目次を目diffしたところ,

  • 5.4.1 Defining Abstract Data Types with Synonym Type definition
  • Chapter11. foreign language interface の追加

の2つが追加されています. Chapter11は見たまんまでしょう. 仕様自体は変わってないと思いますがよく知りません….
1つめの ''AbstractSynonymTypeDef'' については, 以下のような例があるとき,

definition module abstype
:: TA         // abstract typedef
:: TB         // [0] // 実体は実装モジュールファイルで(:==TAと)定義
:: TB :== TA  // [1] // synonym typedef
:: TB(:== TA) // [2] // abstract synonym typedef

型TBは型TAの別名として定義していますが, [0]のように定義するとTBとTAは別の型として扱われます.
[1]のように定義するとTBはTAのエイリアスということが公開されるので, 互いを置き換えて使用する事が出来るようになります.

ここで,[0]の定義ではTBはTAのエイリアスであるという情報がコンパイラにも伝わらないため, 実装が見えている時の最適化が出来ない場合があります.
[1]のように定義すれば実装は見えているので最適化が行えますが, TBとTAは同じ型として扱われてしまうため, 意図したプログラムになりません.
これを解決するため, コンパイラ(のオプティマイザ)にのみ定義を公開し, 実装は隠蔽するための宣言方法が[2]のabstract synonym typedefです.

これについてはどのバージョンから使えるようになっているか検証してませんが,2.4では(当然)使えます.

バグフィックス

Clean IDE, 64bitランタイム, タイププロファイラ, コード生成, コンパイラ
…だそうですが, 詳しくは説明が無いので分かりません.
CleanIDEのプロセスが無駄にforkされる現象は出なくなったことは確認しました.

Generic効率化

アダプタの効率化(よく分からない)と, 言及していない 型情報から生成したコード を削除するようになった.

ダイナミックリンカの効率化

ダイナミックリンカを使った場合,これまで.libファイルに格納されていたオブジェクトコードは分割管理され,ディスクスペースを抑えることが出来る.
(これが普通じゃないんだろうか…?)

TCPIP ライブラリをLinuxMacOSXに移植

Dynamicsライブラリの一部をダイナミックリンカ無しで使えるようになった

Dynamicsを使うには, clm(Cleanコンパイラのコマンド)に -dynamics フラグを付ける.
clmは -dynamics が有効にされたモジュールをリコンパイルしないため, undefined labels linker errorが起こるかも知れない.

Linuxでこのエラーが起きることを確認しました. まっさらな状態からコンパイルすればエラーは起きません.

Linuxにdynamicsが対応しました!

これはメールに書いてませんが, ArchLinuxで試したところ動作が確認できたので紹介します.
MacOSXでの追試(?)を受けてidの型を修正しました*1

// dyn.icl
tos :: Dynamic -> String
tos (d :: Int)    = toString d
tos (d :: String) = d
tos (d :: Real)   = toString d
tos (d :: a->b)   = "<func>"

Start = unwrap polylist
where
	unwrap ds = "["+++(foldl (\ss s=ss+++","+++s) "" (map tos ds))+++"]"
	polylist  = [dynamic "hello, Dynamic!"
				,dynamic 314
				,dynamic 1.1414
				,dynamic id::A.a:a->a
				]
	id x = x
// "[,hello, Dynamic!,314,1.1414,<func>]"

このコードを以下のようにコンパイルするとdynという実行ファイルが作られます.

$ clm -I ../lib/Dynamics -dynamics -nw dyn -o dyn

所感

  • LinuxでDynamicが使えるようになったのは大分嬉しい変更ですね!(MacOSXは手元に環境がないので試せないです…だれか試して下さい…)
  • qualified importはもうちょっとなんとかして欲しいところです… Cleanでは.(どっと)をレコードのフィールドアクセスに使ってしまっているのでHaskellの真似は難しいんですが別名くらいは使いたいですね.