rand(3)を使ってSML# にSML/NJのRandを実装
Basisに乱数無いのは何故なのか?(これ書くの多分3回目くらい)
というわけで(?)、SML#でC言語のライブラリのインポートを試しつつSML/NJが提供している乱数のストラクチャ]を定義してみました。
(* * Rand : RAND (SML/NJ library clone) * * http://www.smlnj.org/doc/smlnj-lib/Manual/rand.html * **) structure Rand : RAND = struct local val srand_ = _import "srand" : word -> unit val rand_ = _import "rand" : unit -> word structure W = Word structure R = Real in type rand = Word.word fun random r = (srand_ r; rand_ ()) val randMin = Word.fromInt 1 (* mingw/include/stdlib.h:#define RAND_MAX 0x7FFF *) val randMax = Word.fromInt 0x7FFF (* SML/NJ : 2147483647 *) fun mkRandom r = let val ctx = ref r in fn ()=> ( let val r_ = random (!ctx) in (ctx := r_; r_) end) end fun norm r = R.fromInt (W.toInt r) / (R.fromInt (W.toInt randMax)) local fun errmsg i j = concat["excepect (i <= j) " ,"actually (i,j)=(",Int.toString i,",",Int.toString j,")"] in fun range (i,j) r = if j < i then raise Fail (errmsg i j) else R.toInt IEEEReal.TO_NEAREST (R.fromInt i + R.fromInt (j - i) * norm r) end end end
インポート命令書くだけなのでホントに楽ですね!インタプリタ上でも同じように書くだけで動作します。これはちょっと感動するレベルですね。
型アノテーションは自分で書く必要がありますが、§ 6.2. C関数の型を見て書きましょう。