久しぶりのDelphi

1995年にBorlandから登場したソフトウェア開発ツールDelphi 1.0には感動しました。私は発売されるとすぐに購入しました。
しかし、いつの間にか Visual Basic やら Java やら C++ やらの進化に気を取られ、Microsoft .NET に翻弄され、Delphi の神髄に触れることなく月日が流れました。たぶん Delphi 3.0 あたりまでバージョンアップしたと思うのですが、小さなアプリを作ったくらいで、だんだん興味を失っていきました。たぶん Windows ネイティブアプリを作ること自身に興味を失っていたからでしょう。

最近私が作りたい(作りたいと思うようになった)ツールには .NET は重すぎて小回りがきかない、と思い始めました。
C++ Builder を使ってみようと思い、Borland Developer Studio 2006 を購入しました。しかし、C++ の流儀をそのまま使えると思いきや、まず VCL の流儀がわからないと話にならない、ということに気づきました。そして残念ながら、オンラインドキュメントの説明は Delphi 中心にしか書かれていなかったのです。
私は Delphi 2006 を本格的に使うようになって半年が過ぎました。Pascal もなかなか快適なスクリプト言語だなあと思い直しました。
WindowsAPI を簡単に呼び出せるし、メッセージハンドラを書くための「メッセージメソッド」という機能が文法に備わっているのも便利です。

CodeGear ブランドの独立、Delphi 2007, C++ Builder 2007, Rad Studio と新製品がいろいろ発表され、これからも安心して使い続けることができそうだなあ、と思っています。
何よりも大きいのは、わからないことの大半がインターネットで調べられる、ということです。多くの開発者の方が実践的なノウハウをウェブサイトにまとめておられることに感謝しています。

この週末は、いままで Excel のマクロでやろうか、Perlスクリプトでやろうか、と思っていたデータの集計作業を Delphi でやってみました。実は CSV ファイルを Grid コントロールに読み込むのは簡単だったのです。

CSV ファイルを TStringList に LoadFromFile して、1行ずつ TStringGrid の row に DelmitedText として代入する。こんな感じです:

procedure LoadCSV(sg: TStringGrid; f: string);
var
  i: Integer;
  lines: TStringList;
  pos : integer;
begin
  lines := TStringList.Create;
  lines.LoadFromFile(f);
  pos := 0;
  for i := 0 to lines.Count - 1 do begin
    // 先頭行は fixed
    sg.Rows[pos].DelimitedText := lines[i];
    Inc(pos);
    if sg.RowCount = pos then
      sg.RowCount := sg.RowCount + 1;
  end;
  lines.Free;
end;

C言語で初めて strtok を覚えて「文字列のトークン化をするのに1文字ずつスキャンしなくてもいいのか」と喜んだのですが、その後 awk を覚えたり perl の split を覚えたりして、トークン化された文字列が配列に一発変換されることに快感を感じました。
同じようなことは Delphi でどうやるんだろう、で思ったのですが「DelimitedText に代入する」というのはなかなか面白いやり方だなあ、と感心しています。

試してみたら、C++ Builder でも同じでした。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	if (OpenDialog1->Execute()) {
		TStringList *lines = new TStringList();
		lines->LoadFromFile(OpenDialog1->FileName);
		for (int i=0; i < lines->Count; i++) {
			String s; // AnsiString
			s = lines->ValueFromIndex[i];
			s.sprintf("%d,%s,%s", 10, "123", s.c_str());
			StringGrid1->Rows[i]->DelimitedText = s;
		}
		delete lines;
	}
}

C++ Buider の String クラスは std::string ではなく、DelphiAnsiString なのです。Delphi を勉強したらやっと C++ Builder も使えるようになってきました。
上記のコードだけ比べると C++ の方が簡潔かなあ、という気もしますが、ValueFromIndex[i] をもっと簡潔に書くにはどうしたらいいのかわかりません。全体としては Delphi で仕事をする方が「心地よい」と感じています。

私が大学に入って最初に覚えたプログラミング言語Pascal でした(大学に入る前に覚えたプログラミング言語もありましたが)。DelphiLinux 版である Kylix はビジネスとしては成功しなかったようで、いま DelphiWindows 専用の開発環境になってしまいました。クロスプラットフォームC++ 開発をした方が将来性がある、という意見もあると思います。しかし、環境依存部分と環境独立部分にシステムをうまく切り分けて、環境依存部分はその環境にもっともふさわしいツールで開発する、という方法も有効ではないかと思います。Visual Studio 2005 で書いた C/C++ のコードは DLL にすれば Delphi から簡単に呼び出せることも確認しました。
Delphi は「作り捨てアプリケーション」から、作り込みとリファクタリングを重ねて「まともなアプリケーション」を作るところまで、いろんな要求をカバーできる言語だなあ、と再認識した今日この頃です。C# などと違って、プログラムを配布するときにランタイムが不要なのも便利ですね。