だらだらと

一日中引きこもり。軽快なJava−Better, Faster, Lighter Javaをほぼ読み終わる。基本的にはJ2EEEJBに対する批判で例えば

  • EJBエンティティ
    • 適している分野 なし
    • 適していない分野 まともなアプリケーション

とか、身も蓋もなくて笑ってしまいました。(^^; データベースとビジネスロジックの分離で悩んでいたので本書で取り上げていたHibernateをちょっと調査してみようかと。.NETへの移植されたNHibernateとかもあります。

あと、半日くらいNemerleと格闘。C#っぽいコードしか書かなければ問題はないのですが、ちょっとでも変わったことをしようとすると嵌り嵌る。ほんとーはNemerle入門記事でも書こうかと思ったのですが、肝心の本人が理解しきれなかったのでお流れ。とりあえず、C#から見ておっと思うところを列挙して茶を濁します。(^^;

・usingは名前空間だけでなくクラスも対象にできる。

using System.Console;

module M {
  Main() : void {
    WriteLine(1 + 2);
  }
}

WriteLineだけで呼び出せます。

・2進数のサポート。

using System.Console;

module M {
  Main() : void {
    WriteLine(10);    // 10進数
    WriteLine(0o10);  //  8進数
    WriteLine(0x10);  // 16進数
    WriteLine(0b10);  //  2進数
  }
}

・数値型いろいろ。

using System.Console;
module M {
  Main() : void {
    WriteLine(10.GetType());  // int
    WriteLine(10u.GetType());  // uint
    WriteLine(10b.GetType());  // byte
    WriteLine(10sb.GetType());  // signed byte
    WriteLine(10l.GetType());  // long
    WriteLine(10ul.GetType());  // ulong
    WriteLine(10f.GetType());  // float
    WriteLine(10d.GetType());  // double
    WriteLine(10.0.GetType());  // double
    WriteLine(10m.GetType());  // decimal
  }
}

Nemerleで変数を宣言するときはintやdoubleといった型を指定しないので覚えておく必要があるかも。例えば、

def x = 10ul;  // unsigned long型 

こんな感じ。

・defとmutable。

using System.Console;
module M {
  Main() : void {
    def pi = 3.14;
    mutable r = 5.0;

    r = 6.0;  // rは変更可能
    WriteLine(2.0 * r * pi);
    WriteLine(r * r * pi);
  }
}

defはreadonly扱いなので変更できません。

・型の別名。

using System.Console;
public type int16 = short;
public type int32 = int;
public type int64 = long;

module M {
  Main() : void {
    def a = int16.MaxValue;
    def b = int32.MaxValue;
    def c = int64.MaxValue;
    WriteLine(a);
    WriteLine(b);
    WriteLine(c);
  }
}

C#のusingはファイル内だけですが、Nemerleではファイル外でもOK。

再帰と反復

using System.Console;

module M {
  // 再帰
  fib1(n : int) : int {
    if (n == 0) 
      0
    else if (n == 1) 
      1
    else
      fib1(n -1) + fib1(n - 2)
  }

  // 反復
  fib2(n : int) : int {
    def iter(a : int, b : int, c : int) : int {
      if (c == 0)
        0
      else if (c == 1) 
        b
      else
        iter(b, a + b, c - 1)
    }
    iter(0, 1, n);
  }

  Main() : void {
    WriteLine(fib1(10));
    WriteLine(fib2(10));
  }
}

fib1はメモリを馬鹿食いしますが、fib2は3つの変数しか保持しない(末尾再帰)です。でもfor文が使えるのだからfor文で書きますよね。(^^;

・リスト処理っぽいこと。

using System.Console;
using Nemerle.Collections;

module M {
  Main() : void {
    def l = [10, 20, 30, 40, 50];
    def print_list<'t>(l : list<'t>) : void {
      match (l) {
        | x::xs => WriteLine(x); print_list(xs);
        | _ => ();
      }
    }
    print_list(l);
  }
}

x::xsの部分はリストのxがリストの先頭要素でxsが残りのリストになります。Lispのcar,cdrみたいなものですね。

Nemerleオブジェクト指向言語関数型言語のハイブリッドが売りなんですが、関数型言語としての使い方を分かっていないため、個人的印象では.NET1.1でGenericsが使え、マクロも便利なベターC#1.0って感じかも。(^^;