C#のインタラクティブシェルを使ってみる

Rubyistおなじみのツールとして、irb というものがあります。1行1行その場でプログラムを評価して結果をすぐに確認でき、メソッドの挙動を確認したり、プログラムの動きを確認したり、簡単な文字列整形に使ったりと、非常に便利なツールです。

こういうことを.NETでしようとおもったら、これまで IronRuby の rbx.exe などの DLR 関連のツールしかありませんでしたが、csharp というインタラクティブシェルコマンドが最近出たということをInteractive C# Shell - Miguel de Icazaという記事で知ったので試してみました。

ダウンロードとインストール

CsharpRepl - Monoによると、Mono 2.2 以上か Subversion リポジトリの9/1の版以降から取得できるとのことです。

まだ、Windows で使用可能な Mono 2.2 のバイナリは公開されていないので Subversion からソースをとってきてビルドします。Windows版をビルドするには Cygwin が必要らしいのですが、僕 Cygwin は大嫌いなので Linux 上でやります。Mono のビルドのやり方はCompiling Mono - Monoに詳しく書いてあります。

csharp コマンドのソースは trunk/mcs/tools/csharp です。Mono.CSharp に依存しててこれを手動で解決する方が大変なのでおとなしく全部ビルドしてしまいます。とりあえず一時的に使うだけのつもりでしたので、うちはこうしました。

ebina@asca$ svn co svn://anonsvn.mono-project.com/source/trunk Mono_svn
ebina@asca$ cd Mono_svn/mono
ebina@asca$ ./autogen.sh --prefix=/opt/mono
ebina@asca$ make
root@asca#  make install
ebina@asca$ export LD_LIBRARY_PATH=/opt/mono:$LD_LIBRARY_PATH
ebina@asca$ export PATH=/opt/mono/bin/:$PATH

早速使ってみる

あとは csharp コマンドを実行すればインタラクティブシェルが立ち上がります。

ebina@asca$ csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> Console.WriteLine("Hello, World!");
Hello, World!

戻り値が IEnumerable を持ってたり、IDictionary をもってたらちゃんと展開してくれます。

csharp> using System.IO;               
csharp> Directory.GetDirectories("/"); 
{ "/bin", "/boot", "/conf.d", "/dev", "/etc", "/home", "/lib", "/lost+found", "/media", "/misc", "/mnt", "/net", "/opt", "/proc", "/root", "/sbin", "/selinux", "/srv", "/sys", "/tmp", "/usr", "/var" }

csharp> using System.Text.RegularExpressions;
csharp> Regex.Matches("isetekishinjyousiki", "i"); 
{ i, i, i, i, i }

csharp> using System.Collections.Generic;
csharp> var dict = new Dictionary<string, string>(); 
csharp> dict.Add("EbIRC", "iseebi");   
csharp> dict.Add("NicoNavi", "icchu"); 
csharp> dict.Add("Mirage", "kazuv3");  
csharp> dict;
{{ "Mirage", "kazuv3" }, { "NicoNavi", "icchu" }, { "EbIRC", "iseebi" }}

初期状態で LINQ も使えるようになってます。

csharp> using System.Collections.Generic;
csharp> var dict = new Dictionary<string, string>(); 
csharp> dict.Add("EbIRC", "iseebi");   
csharp> dict.Add("ZEROProxy", "iseebi");   
csharp> dict.Add("NicoNavi", "icchu"); 
csharp> dict.Add("RiCoLis", "icchu"); 
csharp> dict.Add("Mirage", "kazuv3");  
csharp> dict.Add("Coah", "kazuv3");  
csharp> from item in dict where item.Value == "iseebi" select item.Key; 
{ "ZEROProxy", "EbIRC" } 

Ruby 初級者向けレッスン第22 回」の課題をやってみる

第28回 Ruby/Rails勉強会@関西での okkez さんの初級者レッスンお題が irb だったのですが、この演習問題1つめを csharp でやってみました。

// 1. 1 + 1
csharp> 1+1;
2

// 2. 10 / 4
csharp> 10/4;

// 3. 100 ** 10000
csharp> Math.Pow(100, 10000);
Infinity   // ← double Pow(double x, double y) の限界に達してしまった

// 4. sqrt(16 / 36)
csharp> Math.Sqrt(16 / 36); 
0
csharp> Math.Sqrt(16D / 36D);  // 一度Doubleにしないといけない
0.666666666666667

// 5. BMI を計算してみましょう。BMI = 体重(kg) / 身長(m) ** 2
csharp> 65D / Math.Pow(172D, 2D);
0.00219713358572201

// 6. 1 年は何時間でしょう?
csharp> var hourPerDay = 24;
csharp>  hourPerDay * 365;  
<interactive>(1,16): error CS1002: Expecting `?', `[', `<operator>', or `identifier', got value
csharp> (hourPerDay * 365); // 式だけのときはカッコでくくらないといけない
8760

// 7. 10 年は何分でしょう?
sharp> var minuitePerDay = hourPerDay * 60;
csharp> var minuitePerYear = minuitePerDay * 365;
csharp> (minuitePerYear * 10);
5256000

// 8. わたしが生まれてから9 億3400 万秒経っているとしたら今何歳でしょう?
csharp> var seconds = 934000000D;
csharp> var minuites = seconds / 60D;
csharp> var hours = minuites / 60D;
csharp> var days = hours / 24D;
csharp> var years = days /365D;
csharp> years;
29.6169457128361

試してみて

やっぱり、.NET のクラスを実際に扱えるのは便利で楽しいです。LINQ が使えるのも大きいです。Windows 版のバイナリ誰か作ってくれないかなぁ。

あとは VisualStudioMonoDevelop に統合されたり、InteliSense が効くようになれば最強だと思います。今後に期待です!