はじめてのNemerleその2
昨日に引き続き、Nemerleネタで。まず、コンパイルの仕方から。Nemerleではソースファイルの拡張子に.n(例:hello.n)を使用します。 で、これをコンパイルするにはコマンドプロンプトから、
$ ncc -texe -o hello.exe hello.n
このようなコマンドを実行します。出力ファイル名を省略するとout.exeになります。
DLLを作成する場合は、
$ ncc -tdll -o hello.dll hello.n
と指定しればOKです。
ところで、Nemerleのソースコードをチェックアウトしてくるとその中にnemerle.vimというシンタックスファイルがあります。エディタにvimを使っている方はシンタックスファイルを自作しないで済みます。>と、vimの宣伝(^^;
では、Nermeleの機能について見ていきます。まずは、高階関数です。高階関数と書くと難しそうですが、関数ポインタを引数にとる関数みたいなものです。Nemerleではこれを次のように書きます。
Method(function : int * int -> int) : int { ... }
まず、int * int -> intに注目して下さい。int * intというのは2つのint型引数を意味しています。また->intはint型へ変換です。これらから、仮引数functionはint型引数2つを取り、int型の戻り値を持つ関数であることが分かります。では、サンプルを見てみましょう。
using System; module M { Pass(x : int) : int { x; } SecondPower(x : int) : int { x * x; } Sum(arr : array<int>, f : int -> int) : int { mutable sum <- 0; for (mutable i <- 0; i < arr.Length; ++i) { sum <- sum + f(arr[i]); }; sum; } Main() : void { def arr = array[1,2,3,4,5]; Console.WriteLine(Sum(arr, Pass)); Console.WriteLine(Sum(arr, SecondPower)); } }
関数Sumは引数に配列と関数を取り、配列要素に関数を適用した結果の合計を返します。ここではSumにPass(そのまま)とSecondPower(二乗)の2つを渡しています。それぞれ、単純な合計と二乗の合計が返ってくることになります。あ、何の断りも無くmoduleを言うキーワードを使ってしまいましたが、これはC#2.0で追加されるstatic classと同様、全てのメンバがstaticとなるクラスみたいなものです。
ところで、先ほどの例ではPassやSecondPowerと行った関数を用意しましたが、これらは関数と言うより、コードの断片に近いです。高階関数に渡す処理毎に関数を作っていたら細々とした関数でいっぱいになり、分かり難くなってしまいます。こういう場合にλ式を使うといちいち関数を作らずに済むので便利です。先ほどの例をλ式を使って書き直すと次のようになります。
using System; module M { Sum(arr : array<int>, f : int -> int) : int { mutable sum <- 0; for (mutable i <- 0; i < arr.Length; ++i) { sum <- sum + f(arr[i]); }; sum; } Main() : void { def arr = array[1,2,3,4,5]; Console.WriteLine(Sum(arr, fun(x:int):int{x})); Console.WriteLine(Sum(arr, fun(x){(x:int)*x})); } }
PassもSecondPowerも無くなりました。funというキーワードがλ式を表しています。最初のλ式はint型の引数を取り、int型の戻り値を持つ関数を表し、{}の中に処理が書かれています。ところで2つ目のλ式を見て下さい。引数の型も戻り値の型も指定されていません。これはどんな関数を意味しているのでしょうか。関数本体を見ると(x:int)と書かれているところがあります。これはNemerleにおけるキャスト構文で、xをint型にキャストしています。実は、そこから連鎖的にx*xがintとなり、戻り値もint型となるのです。このようにλ式を書くときは型に対するヒントがあれば型推論してくれるので明示的に型を書く必要が無いのです。
とか、言ってますが実はあんま自信ないです。資料不足のため実際に動かした結果から推測しているで怪しいです。間違っていたら、ごめんなさい。(^^;
ちょっと長くなったので続きは明日へ。次はC#2.0やJava1.5でサポートされたGenericsについて紹介したいと思います。そーなんです、Nemerleは既にGenericsをサポートしているんですよ。