ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

「すべてがFになる」読了

すべてがFになる (講談社文庫)

すべてがFになる (講談社文庫)

森博嗣のデビュー作らしい。S&Mシリーズの原点というわけではないらしい。
いきなりネタバレですが、タイトルのFは16進数のFです。すべてがFってのはFFF・・・みたいな。
そうそう。現在僕が開発に携わってるシステムでも、FFFFFFが意味持ってます。だってアセンブラバイナリファイルなんだもん。DBなんてものは無かったのさ(いや、あっただろうけど、当時はまだ実用じゃなかったってのが正しいのか?)ちなみに携わってるだけで、開発はしてません。ていうか出来ないし。興味もほとんどないし。
さて本書。いきなり天才プログラマが出てきます。3巻で天才数学者ってのも出てきますが、天才プログラマの方が上だな。名前も真賀田 四季(まがた しき)ってのがいいね。
プログラマとして惹かれたのは、本書中に出てくる環境レッドマジック。

開発環境がものすごく充実しているのよ。ここだけのシステムだわ。これを一度経験したら、他のところでは働けない。

って、どんなシステムよ!経験してー。
実はこのレッドマジックは、天才プログラマが作ったもので、建物の入退室管理やら、電話やら、色々制御しているんですが、物語のキーにもなっていたりします。ソフトウェア業界に関わっている人なら、読んで見ると面白いかも。
そういえば、僕が読んだ小説で、○○な人なら面白いかも。って結構書いたような記憶があるんですが、○○に「ソフトウェア業界に関わっている人」なんて書く日が来るとは思いませんでした。


ところで、冒頭で「オブジェクト指向システム設計入門」という本の引用が載ってます。
どんなもんかとAmazonで調べてみたら、書評を見た感じでは、なんだかぱっとしない本みたい。
1993年の本だし古いかなー。丸善に寄ったときは見てみよう。

デリゲート

プログラミングC# p286

12章から「デリゲートとイベント」ということで、C#のウリの一つ(?)であるデリゲートの説明になるわけですが、のっけから、

例えば州知事が亡くなった場合、

とか不吉な出だしになってます。
イベント処理で使うのだということはなんとなく分かるのですが、こまごました説明を読んでも良く分からないので、12.1に書いてある

デリゲートの機能は、C++など多くの言語においての関数ポインタやメンバ関数を指すポインタとほぼ同じものです。

を元にサンプルを書いてみる。
実は、先日書いた関数を関数に渡す@C言語のエントリは、このコメントから着想しています。
で、サンプル。

using System;

class FunctionPointer
{
        public delegate int twoitem(int a, int b);

        public static int add(int a, int b)
        {
                return a + b;
        }

        public static int sub(int a, int b)
        {
                return a - b;
        }

        static void Main(string[] args)
        {
                // 関数ポインタを定義
                FunctionPointer.twoitem fp;

                fp = new FunctionPointer.twoitem(FunctionPointer.add);
                Console.WriteLine("result = {0}", fp(5, 3));

                fp = new FunctionPointer.twoitem(FunctionPointer.sub);
                Console.WriteLine("result = {0}", fp(5, 3));
        }
}

結果はこう。

result = 8
result = 2

delegateっちゅうのは、要はメソッド自体の入れ物で、カッコ付ければコールできると。まあそんな感じでしょう。
Java的にはインタフェース使って書くようなところでしょう。
それはこんな感じ。

public class FunctionPointer
{
        public static void main(String[] args)
        {
                TwoItem ti = new Add();
                System.out.println("result = " + ti.twoitem(5, 3));

                ti = new Sub();
                System.out.println("result = " + ti.twoitem(5, 3));
        }
}

interface TwoItem
{
        public int twoitem(int a, int b);
}

class Add implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a + b;
        }
}

class Sub implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a - b;
        }
}

結果は同じ。

result = 8
result = 2

C#で書いても似たようなものだと思います。インタフェースでなくデリゲートな理由は、p287にもあるように、

これはインターフェイスを使って実現できるでしょう。しかしデリゲートはインターフェイスよりも小さく、粒度が細かいのです。

というわけで、interfaceとか、その実装classとかを用意しなくても、少ないコード量で多態性を実現できる仕組みと捕らえるのが良いようです。

マルチキャストデリゲート

プログラミングC# p297

デリゲートに複数のメソッドを登録すると、順番に呼んでくれます。

using System;

class MulticastFunctionPointer
{
        public delegate void hello();

        public static void hello_Japanese()
        {
                Console.WriteLine("こんにちは");
        }

        public static void hello_English()
        {
                Console.WriteLine("hello");
        }

        public static void hello_Spanish()
        {
                Console.WriteLine("HOLA!");
        }

        static void Main(string[] args)
        {
                // 関数ポインタを定義
                MulticastFunctionPointer.hello fp;

                fp = new MulticastFunctionPointer.hello(MulticastFunctionPointer
.hello_Japanese);
                fp += new MulticastFunctionPointer.hello(MulticastFunctionPointe
r.hello_English);
                fp += new MulticastFunctionPointer.hello(MulticastFunctionPointe
r.hello_Spanish);

                fp();
        }
}

+=で連結しているのがミソですね。ちなみに結果はこう。

こんにちは
hello
HOLA!

なんだか、JavaScriptのaddEventListenerみたいな感じ。

<html>
<head>
<script language = "JavaScript">
function aaa()
{
	alert("aaa");
}

function bbb()
{
	alert("bbb");
}

function OnLoad()
{
	document.form1.button1.addEventListener("click", aaa, true);
	document.form1.button1.addEventListener("click", bbb, true);
}
</script>
</head>
<body onLoad = "OnLoad()">
<form name = "form1">
	<input type = "button" name = "button1" value = "押して">
</form>
</body>
</html>

ボタン押すと、関数aaaと関数bbbが両方実行されます。
このサンプルの方が、よっぽどマルチキャストデリゲートを説明してるな。。

匿名メソッド

プログラミングC# p315

Javaでいう匿名クラスみたいなものか?

using System;

class FunctionPointer
{
        public delegate int twoitem(int a, int b);

        public static int add(int a, int b)
        {
                return a + b;
        }

        public static int sub(int a, int b)
        {
                return a - b;
        }

        static void Main(string[] args)
        {
                // 関数ポインタを定義
                FunctionPointer.twoitem fp;

                fp = FunctionPointer.add;
                Console.WriteLine("result = {0}", fp(5, 3));

                fp = FunctionPointer.sub;
                Console.WriteLine("result = {0}", fp(5, 3));

                fp = delegate(int a, int b)
                {
                        return a * b;
                };
                Console.WriteLine("result = {0}", fp(5, 3));
        }
}

結果はこう。

result = 8
result = 2
result = 15

multメソッドを用意しなくても、いきなりコードブロックで掛け算の処理がかけるってわけです。
ちなみに、さっきのJavaの例を無名クラスで同じように拡張するとこんな感じ。

public class FunctionPointer3
{
        public static void main(String[] args)
        {
                TwoItem ti = new Add();
                System.out.println("result = " + ti.twoitem(5, 3));

                ti = new Sub();
                System.out.println("result = " + ti.twoitem(5, 3));

                ti = new TwoItem()
                {
                        public int twoitem(int a, int b)
                        {
                                return a * b;
                        }
                };
                System.out.println("result = " + ti.twoitem(5, 3));
        }
}

interface TwoItem
{
        public int twoitem(int a, int b);
}

class Add implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a + b;
        }
}

class Sub implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a - b;
        }
}

もちろん結果はこう。

result = 8
result = 2
result = 15