あどけない話

インターネットに関する技術的な話など

名詞の王国

君のプログラミング言語で、これ、できる?」で紹介されていた「Execution in the Kingdom of Nouns」を訳してみました。英語よりも、つたない日本語訳の方がよい方は、どうぞ。

おかしな訳があれば、教えて下さい。適宜、訂正します。

「C の関数はファーストクラスじゃないよ」などの突っ込みは、原文の著者へどうぞ。

名詞の王国での実行

彼らには気分ってものがある。ものによるが...特に動詞がそうだ。誇り高いことったらない...形容詞相手ならなんとでもできるが、動詞はどうしようもない...じゃが、このわしにかかれば皆思いのまま!

-- ハンプティ・ダンプティ

世界のみなさん、こんにちは!今日は、邪悪な王 Java の物語と国中の動詞を滅ぼした彼の冒険について語ろう。

警告:この物語は幸福な結末を迎えない。心臓の弱い人や批判家向けではない。もし、あなたが怒りっぽい性格であるか、ブログのコメントですぐに荒らしをしてしまうのなら、ここで読むのを止めて頂きたい。

話を始める前に、頭をすっきりさせよう。

ゴミ溢れ

すべての Java ユーザは、ユースケースが好きだから、ユースケースの一例から始めよう。それは、ゴミ出し。こんなときのこと。「ジャーニー、そのゴミを出してきて!溢れそうじゃないの!」

もしあなたが、英語を喋る本当に普通の人であり、ゴミ出しの際の行動を説明しろと言われたら、おそらくこんな風に考えるだろう。

  • 流しの下からゴミ袋を取り出す
  • それをガレージに運び出す
  • それをゴミ箱に入れる
  • 家の中に戻る
  • 手を洗う
  • ソファーに座る
  • ビデオゲーム(あるいは、やっていたこと)を再開する

もしあなたが英語で考えてなくても、あなたの好きな言語でも、似たような一連の動作を考えただろう。言語の選択に関わらず、動作に程度の差こそあれ、ゴミ出しとは、ゴミを外に持って行って、家に戻ってくる、一連の動作である。

我々の心は、押さえきれない行動で満たされている:我々は暮らし、呼吸し、歩き、話し、笑い、泣き、望み、恐れ、食べ、飲み、止め、進み、ゴミを出す。これ以外にも、我々は何をするにも、どう行動するのも自由だ。もし、我々が太陽の照りつける中の動かない石だとしても、人生は悪くはない。しかし、自由ではないだろう。自由とは、我々が何かするという能力から生じるものである。

もちろん、我々の心は、名詞によっても満たされている。我々は、名詞を食べ、店で名詞を買い、名詞に腰掛け、名詞の上で眠る。名詞はあなたの頭の上に落ち、あなたの名詞の上に大きな名詞を作ることもある。名詞とは物であり、物なしで我々は存在できるだろうか? しかし、それらは単に物であり、それだけである:目的への手段、目的そのもの、高価な財産、あるいは、我々が観察する物の名前。ビルがある。ここに岩がある。どんな子供でも、名詞は認識できるだろう。これらの名詞を面白くするのは、名詞に対する変化である。

変化には行動が必要だ。行動は、人生に刺激を与える。行動は、刺激に刺激を与えさえする!結局、食べなければ、それは刺激的(スパイシー)ではないのだ。名詞はどこにでもあるが、人生の絶え間ない変化と変わらぬ興味は、すべて動詞の中にある。

そして、もちろん、動詞と名詞に加えて、我々には、形容詞、前置詞、代名詞、冠詞、接続詞、魅惑的な虚辞、そして、考えや話を面白くしてくれる他の言葉がある。すべての人が、それぞれに役割があり、すべてが重要だと同意してくれると思う。どれか一つでも失ったら、大変なことだ。

もしも我々が、これから決して動詞を使わないと突然決めてしまったら、それはおかしなことではないだろうか?

まさにそんなことが起こっている国の物語について、話をさせて欲しい。

名詞の王国

Java がシリコンの拳をもって統治する Java 王国では、あなたや私のような考え方は、人々に許されていない。Java ランドでは、王自らの命令により、名詞がとても大切にされている。名詞は、王国のもっとも重要な市民なのである。彼らは、きらびやかな装飾品を身にまとって歩いている。それらは、比較的平穏な人生を送っている形容詞によって用意されたものである。形容詞は、名詞ほど地位は高くないが、動詞に生まれてこなくて本当によかったと考えている。

なぜなら、王国の動詞市民は、苦渋をなめているからである。

Java ランドでは、王 Java の命令により、動詞は名詞によって所有されている。しかし、彼らは単なるペットではない。それどころか、動詞は Java ランド全土のすべての雑用と肉体労働をしなければならない。事実上、彼らは奴隷、少なくとも農奴か使用人である。Java ランドの住人は、この状況に大変満足しており、違う世の中もあり得ることにまったく気付いていない。

Java ランドの動詞は、すべての仕事に責任があるにも関わらず、軽蔑されており、自由に歩き回ることは許されていない。動詞が人前に出ようとするなら、必ず名詞にエスコートしてもらわなければならない。

もちろん、「スコートする」とう動詞自身も、一人で歩き回ることは許されていない。エスコートすることを促進するためには、VerbEscorter を斡旋する必要がある。では、「促進する」(facilitate)や「斡旋する」(procure)はどうなのか? 同様に、Facilitator や Procurer が重要な名詞である。それらの仕事は、それぞれ促進や斡旋によって、卑しい動詞「促進する」と「斡旋する」を監視することである。

神 Sun の導きにより、王は常に Java 王国からすべての動詞を追放すると脅している。もしこれが現実となれば、住人はすべての雑用をこなす、少なくとも一つの動詞を必要とするだろう。ユーモアのかけらも持ち合わせていない王は、きっと execute を選択するだろう。

動詞 execute や、仲間の run、start、go、JustDoIt、makeItSo などは、適切な Executioner と execute の呼び出しに置き換えることで、他の動詞の仕事をこなすことができる。ちょっと待って、だって? Waiter.execute()。歯を磨く? ToothBrusher(myTeeth).go()。ゴミを出す?TrashDisposalPlanExecutor.doIt()。安全な動詞などいない。すべては、名詞に置き換えられるのだ。

Java ランドの最も狂信的な地域では、名詞は完全にすべての動詞を追い出したとされる。しかし、そこら中に動詞がまだいるのではないか疑問を抱くももっともだ。畑を耕すためや、し尿瓶を空にするためにだ。注意深く観察すると、秘密が暴かれる。名詞は、自分が所有する動詞 execute の名前を、その機能を少しも変えることなしに、自分たちにちなんで、変えることができる。FieldTiller till()、ChamberPotEmptier empty()、RegistrationManager register() を観察すれば、所有者である名詞の皮を被った、邪悪な王の軍隊に属する executioner の一つであることが分る。

隣国の動詞

近隣のプログラミング言語王国では、ゴミを出すことは単純であり、上記のような方法に近い。Java と同様に、データは名詞であり、関数は動詞である。しかし、Java ランドと異なるのは、諸王国の市民は、彼らの都合に合わせて、自由に名詞と動詞を混ぜたり、組み合わせたりすることができる。

たとえば、C ランド、JavaScript ランド、Perl ランド、Ruby ランドという近隣諸国では、ゴミ出しを一連の動作、すなわち、動詞(関数)としてモデル化するかもしれない。一連の動作を、適切なオブジェクトに適切な順番で適応すれば(ゴミを持つ、外に出す、ゴミ箱に捨てる、等々)、ゴミ捨ての仕事は完全に成功する。過剰なエスコートや、監視人はどこにも必要ない。

これらの王国では、動詞をくるむ名詞を作る必要はほとんどない。ゴミを見つけるための名詞 GarbageDisposalStrategy や GarbageDisposalDestinationLocator、あるいは ソファに戻ってくるための名詞 PostGarbageActionCallback はない。単に名詞に作用する動詞を書き、それらを適切な順番で実行する動詞 take_out_garbage を用意すればよい。

それらの近隣王国では、必要とあれば、重要な名詞を作る方法も用意されている。もし熱心な発明者が、畑を人よりも早く耕すことのできる馬/車/機械のような、これまでに存在していなかった新しく有益な概念を作るのなら、名前/説明/状態/命令を提供するクラスを利用できる。

違いは、動詞は独立して存在でき、それを所有する新たな名詞を作り出す必要がないことだ。

これがプログラミング諸国のもののありかただ。Java ランドの住人は、近隣王国の人々を軽蔑している。

地中深く穴を掘って行くと...

この星の裏側には、人口の少ない地域があり、そこでは動詞が高貴な市民とされている。それらは、Haskellia、Ocamlica、Schemeria などの関数型王国だ。そこの住人は、Java ランド近隣王国に行くことは、ほとんどない。近くに王国があまりないせいで、関数型王国同士は互いを軽蔑しており、他にすることがないと戦争を起こす。

関数型王国では、名詞と動詞の身分は等しいとされている。しかし、名詞が名詞たろうとするなら、なにもしないで座っているほかない。動詞は大変行動的で、すべてをこなすので、名詞はほとんど何もしない。動詞をエスコートする名詞を作れという変な法律はない。だから、それぞれの王国には、正確に物の数だけ名詞が存在する。

その結果、こういうのも変だが、動詞が国の主導権を握っている。よそ者からみると動詞(すなわち関数)が群を抜いて重要な市民であるという印象を持つだろう。蛇足ながら、それが、物型王国ではなく、関数型王国と呼ばれる所以である。

最果ての地、関数型王国の向こうには、神聖 Lambda 王国 と呼ばれる伝説の国がある。そこには、名詞はまったくなく、動詞のみがある!物は存在するがが、すべては動詞から作られる。もし伝承が本当であれば、羊を数える数字(その国で通貨をやりとりするための普通の方法でもある)さえもそうだ。0 は、単に lambda()。1は、lambda(lambda())、2 は lambda(lambda(lambda()))、といった具合だ。この伝説の国では、すべての物、名詞、動詞、その他すべてのものは、根源的な動詞 lambda から作られる。

正直なところ、Java ランドの住人は星の裏側の存在に気付いていないため、心穏やかだ。彼らのカルチャーショックを想像できるだろうか? 気持ちを表すためには、彼らは外国人恐怖症といった新しい名詞を発明しなければならず、混乱するだろう。

Java ランドの住人は幸せか?

Java ランドでの生活は、よく言えば少し変で、悪く言えばひどく効率が悪いといえる。しかし、子供の詩を知れば、彼らが詩的で、社会がいかに幸せかが分るだろう。たとえば、Java ランドの子供達は、有名な警句をしばしば暗唱する。

釘が一本なければ、

    // (訳註) 馬蹄がダメになる
    throw new HorseshoeNailNotFoundException("no nails!");

馬蹄がなければ、

    // (訳註) ウマがダメになる
    EquestrianDoctor.getLocalInstance().getHorseDispatcher().shoot();


ウマがなければ、

    // (訳註) 騎手がダメになる
    RidersGuild.getRiderNotificationSubscriberList().getBroadcaster().run(
      new BroadcastMessage(StableFactory.getNullHorseInstance()));

騎手がいなければ、

    // (訳註) 通信がダメになる
    MessageDeliverySubsystem.getLogger().logDeliveryFailure(
      MessageFactory.getAbstractMessageInstance(
        new MessageMedium(MessageType.VERBAL),
        new MessageTransport(MessageTransportType.MOUNTED_RIDER),
        new MessageSessionDestination(BattleManager.getRoutingInfo(
                                        BattleLocation.NEAREST))),
      MessageFailureReasonCode.UNKNOWN_RIDER_FAILURE);

通信がなければ、

    // (訳註) 戦闘がダメになる
    ((BattleNotificationSender)
      BattleResourceMediator.getMediatorInstance().getResource(
        BattleParticipant.PROXY_PARTICIPANT,
        BattleResource.BATTLE_NOTIFICATION_SENDER)).sendNotification(
          ((BattleNotificationBuilder)
            (BattleResourceMediator.getMediatorInstance().getResource(
            BattleOrganizer.getBattleParticipant(Battle.Participant.GOOD_GUYS),
            BattleResource.BATTLE_NOTIFICATION_BUILDER))).buildNotification(
              BattleOrganizer.getBattleState(BattleResult.BATTLE_LOST),
              BattleManager.getChainOfCommand().getCommandChainNotifier()));

戦闘がなければ、

    // (訳註) 戦争がダメになる
    try {
        synchronized(BattleInformationRouterLock.getLockInstance()) {
          BattleInformationRouterLock.getLockInstance().wait();
        }
    } catch (InterruptedException ix) {
      if (BattleSessionManager.getBattleStatus(
           BattleResource.getLocalizedBattleResource(Locale.getDefault()),
           BattleContext.createContext(
             Kingdom.getMasterBattleCoordinatorInstance(
               new TweedleBeetlePuddlePaddleBattle()).populate(
                 RegionManager.getArmpitProvince(Armpit.LEFTMOST)))) ==
          BattleStatus.LOST) {
        if (LOGGER.isLoggable(Level.TOTALLY_SCREWED)) {
          LOGGER.logScrewage(BattleLogger.createBattleLogMessage(
            BattleStatusFormatter.format(BattleStatus.LOST_WAR,
                                         Locale.getDefault())));
        }
      }
    }


戦争がなければ、

    // (訳註) 国がダメになる
    new ServiceExecutionJoinPoint(
      DistributedQueryAnalyzer.forwardQueryResult(
        NotificationSchemaManager.getAbstractSchemaMapper(
          new PublishSubscribeNotificationSchema()).getSchemaProxy().
            executePublishSubscribeQueryPlan(
              NotificationSchema.ALERT,
              new NotificationSchemaPriority(SchemaPriority.MAX_PRIORITY),
              new PublisherMessage(MessageFactory.getAbstractMessage(
                MessageType.WRITTEN,
                new MessageTransport(MessageTransportType.WOUNDED_SURVIVOR),
                new MessageSessionDestination(
                  DestinationManager.getNullDestinationForQueryPlan()))),
              DistributedWarMachine.getPartyRoleManager().getRegisteredParties(
                PartyRoleManager.PARTY_KING ||
                PartyRoleManager.PARTY_GENERAL ||
                PartyRoleManager.PARTY_AMBASSADOR)).getQueryResult(),
        PriorityMessageDispatcher.getPriorityDispatchInstance())).
      waitForService();

すべては釘一本のせい。

今日においても、これは有益な教訓だ。

Java ランドでの語り口は、Ben Franklin のオリジナル作品といくつかの点で違っているが、Java ランドの住人はこれは魅力的な詩であると感じている。

魅力は、その構造様式だ。その構造様式は、すべて名詞からなるため、王 Java から格別の評価を与えられている。知っての通り、Java 王国では、名詞は物であり、物はすべての行動よりも尊重される。構造様式は、あなたが見たり触ったりできる物、あなたの頭上に堂々とそびえる物、そして、棒でたたけば心地よい音を奏でる物から作られる。王は馬車に乗り、車輪を叩きながら、この上なく満足している。できが悪かろうが、この詩には物の不足はない。

我々の人間としての本能は、物の中からシェルターを探す。シェルターが強ければ強い程、我々はより安全に感じる。Java ランドでは、人々を安心させる強い物がたくさんある。彼らは、多量の構造的生産物に驚嘆し、「これは頑健な設計に違いない」と考える。構成を変えようとしたときに、この思いはさらに強くなる。構造様式の強さに、人々はたじろぐ。誰も構成を破壊できはしないと思える程に。

強固な構造様式に加えて、Java ランドのすべての物は、上手に組織化されている。すべての名詞は、適切な位置に発見できる。すべての話が、限定された形をとる。オブジェクトの生成は、よい例だ。それぞれの抽象化に対してマネージャが一つ。マネージャごとに run()メソッドを一つだけ。Java の住民は、経験が少なくても、この種のモデル化でどんな話も表現できると悟る。どんな抽象化の表現も、どんな計算の表現も可能にする名詞カルキュラスが存在するのだ。必要なのは、十分な名詞、それらを生成するコンストラクタ、名詞のグラフを横断するアクセッサ、そしてプランを実行する極めて重要な execute() だ。

Java 王国の住人は単に幸せというだけではなく、誇りで充満している。

StateManager.getConsiderationSetter("Noun Oriented Thinking", State.HARMFUL).run()

あるいは、Java 王国以外の言葉で言えば、「名詞指向の考え方は有害だ」。

オブジェクト指向プログラミング(OOP)は、まず最初に名詞を置く。どうして、話の一部として具象化した部分を置くのか?どうして、一つの概念が、他に優先されるのか?突然 OOP が、我々が考えているほど動詞は重要でないと決めた訳ではあるまいし。私の友達 Jacob Gabrielson が表現したように、オブジェクト指向プログラミングは、パンツ指向の服のようだ。

他と同様に、Java の静的型付けシステムには、いくつか問題がある。しかしなによりも、名詞指向の考え方を過度に強調されるのは、心をかき乱される以上のことだ。どんな型システムであれ、あなたの考え方をいくぶんシステムに合わせるように要求するが、単独の動詞を排除することは、まったく理にかなわない。

C++ は、この問題を露呈させない。なぜなら、C の上位互換である C++ は、単独の関数を許している。しかも、C++名前空間の抽象化も提供する。Java はクラスのアイディアに、名前空間、ユーザ定義の型、構文委譲の仕組み、スコープの仕組みなどを詰め込んだ。

気を悪くしないで欲しい。私は、C++ が「よい」と主張しているのではない。しかし、少なくとも Java と比較すると、型システムの柔軟さは評価に値すると思う。C++ は、一見正しく見える文があなたを殴ったり殺そうとしたりする(つまり、予期せぬセグメンテーションフォールトや他の落とし穴)問題に苦しんでいる。そして、C++ は、ある考えを表現するための呪文を見つけることは極めて困難だ。だが、考えを簡潔に表現する能力は、Java よりも遥かに上だ。なぜなら C++ には動詞がある。誰が、しゃべるのとは違う方法を望むというのか?

クラスは、Java が提供する唯一のモデル化ツールだ。アイディアを思いついたときはいつも、たとえそれが、行動や行為、あるいは物ではない概念であったとしても、それが物になるように包み込む必要がある。

結局私は、Perl ユーザが8年か9年前に私に言ったことに賛成だ:「おいおい、すべてが物ではないんだよ」

Java だけが徹底的な名詞中心のオブジェクト指向言語であることは奇異なことだ。AbstractProxyMediator や NotificationStrategyFactory なんかは、PythonRuby のどこにも見当たらない。どうして Java には、そこらかしこにあるのか? 違いは、きっと動詞にある。Python、Rupy、JavaScriptPerl、そしてもちろんすべての関数型言語は、クラスに包むことなしに、関数を定義したり、受け渡したりできる。

これは、動的型付け言語ではとても簡単だ。名前から得られる関数の参照を渡すだけだ。そして、その関数に適切な引数を与えて実行したり、返り値を使ったりするのは、呼び出し側の自由だ。

静的型付け言語でも、第一級(ファーストクラス)関数を提供している。これには、C や C++ のように明示的に型を指定する言語、そして、Haskell や ML のような型推論言語が含まれる。言語には、適切な型シグニチャとともに関数リテラルを生成したり、引き渡したり、呼び出したりできる文法が必要だ。

Java が第一級関数を追加して、我々が考えるように動詞を使える成熟し歪みのない世界へ仲間入りできない理由はなにもない。事実、JVM を利用する Nice (http://nice.sourceforge.net)と呼ばれる言語は、Java のような文法を持ち、同時に単独の関数を利用するための機能を持つ。Java では、参照するために、CallBack や Runnable か、他の無名インターフェイスで包まなければならない。

Sun は、関数はクラスによって所有されるという習慣を破る必要はない。すべての無名関数は、定義されたクラスへの暗黙的なポインタ this を運べればよい。問題解決。

どうして Sun が Java を名詞の王国にとどめようとしているのか私には分らない。私は、支持者を過小評価しているのではないかと疑いを持ってる。Sun はジェネリクスを追加した。それはとても複雑な概念であるから、注意深く言語を簡潔に保とうとはしてないことは明らかだ。それは悪いことではない。なぜなら Java の地位は確立しているから。我々が考えるように Java でプログラミングできるようにすることは理にかなっている。

私が、ゴミを出し、ビデオゲーム、あるいはやっていたことに戻れるように、私は彼らがこの問題を直してくれることを望む。