LLDN (6) - キミならどう書く

LL*名物。去年のお題も素敵だったけれど、今年は漢数字電卓。それぞれの言語の個性が炸裂して面白かった。

今年のお題は、

  • 数字を漢数字で表記。

    • 表記法は、万以上が4桁ごとに統一されたタイプではなくて、恒河沙以上が8桁ごととなる難しいタイプのものだ。今即興でググって見つけた 無量大数の彼方へ によれば、これは「塵劫記」の寛永8年版によるものだそうだ。私がなじんでいる全部4桁ごとのタイプは寛永11年版だそうだ。
  • 計算式は中置記法演算子は「+」「−」「×」「÷」

  • 出力も漢数字
  • 計算過程の内部形式は自由。切り捨てで生じる誤差等細かいことは拘らない。拘ってもいい。

Haskell

まずはHaskellから。資料は lldn_haskell_calc.zip にある。

Haskellはいきなり飛ばしてくれた。いまいち、文法を理解し来ていない部分もあるので不正確かも知れないけれど、

  • Monadを使ってParser型構築子を記述
  • Praser型構築子で段階的に、parserを構成

    • 1桁の漢数字のparserを構築
    • それを使って、漢数字のparserを構築
    • それを使って、漢数字の加減のparserを構築
    • それを使って、漢数字の加減乗除のparserを構築
      • 加減の構築と、そこからの乗除の構築は似ているので、当然高階関数で共通化
    • それを使って、最終的に式parserを構築

うわっ。Haskellだ。

パース結果は次のような感じのExpr型になっている。

 data Expr
   = Number Integer
   | BinOpApp BinOp Expr Expr
 data BinOp = Add | Sub | Mul | Div

これを再帰的に評価してMaybe Rationalに落とすeval関数を定義。この辺は関数型言語の素直な記述になっていて、この辺は私でも十分理解できる(多分書ける)

その後、自由演技としてチャーチ数電卓を披露してくれた。整数の演算をチャーチ数で出力してくれる。当然の事ながらすごく長い。小飼さんの要望に答えて10の階乗を評価してみせてくれたけれど、展開中に発表時間終了となった。階乗のチャーチ数って、評価にどれだけ時間がかかるんだろう。

実にHaskellらしい最高の発表であった。 Pugs はとある天才が1ヶ月でHaskellを覚えて1ヶ月で実装したそうだけれど、Haskell使いは偉い。

Perl

Perlは言語である以上に文化だ。そしてCPANがある。車輪の再発明は悪である。というわけでCPANをあたったそうだけれど、結局適当なものがなかったとか。 アイディアとしては

三百 => 百百百 => CCC

の要領で正規表現でローマ数字に落として更にMath::Romanあたりのローマ数字変換モジュールを使うというのがあったらしいけれど、

六百 => DC

とかなると大変なので却下したと言うこと。CPAN! 正規表現! Perlらしくて素晴らしい。結局、自前で漢数字をアラビア数字に変換するメソッドを書いて、そうすれば普通のperlの計算式になるから、後はevalに掛けたそうだ。eval!!これも素晴らしい。最後は漢数字に逆変換。

……ところが、調べたときは無かったのに、いつの間にかこっそりと小飼さんが Lingua::JA::Numbers なんてものを作っていて、結局perl的にはこれを使うのが正道であったという落ちがついた。

資料は LL2005_KB_perl.zip

自由演技では、確かXMLRPCで徹底的にこのモジュールを使い倒すというのをやってくれたと思う。

Python

規定演技は、再帰下降法によるスタンダードな解析を行い、値を評価。資料は kalc_python.zip

自由演技が演出上手だった。Python/tkでGUI漢数字電卓を作って、最初は普通の電卓と思わせて置いて、実はウィンドウを広げると隠れていたボタンが次々に出てきて、

  • 無限メモリー機能
  • 「電卓に付いてるメモリー演算ボタンがM+だけなのはおかしい」ということで、任意の演算子ボタンを引数に取ってメモリー値と表示値との演算を行うopMボタン。(高階関数ボタンと表現していた)

これだけでも会場を沸かせていたけれど、更にウィンドウを広げると、任意のPython関数を入力して演算子ボタンを作ってしまう機能が現れた。単項演算子も2項演算子も作れる。流石LL。

初めは平凡なGUI電卓と見せかけて次々と意外な展開をみせる話術が巧みだった。

Ruby

待ってました。Rubyです。発表者が青木さんだし、ここは当然 racc / strscan で解析する。rubyistには常識だやな。raccのおかげでparserは短いコードで生成できていた。

問題はデータ構造となるけれど、これは配付資料 lldn-calc-ruby.zip に入ってるindex.htmlと図を見てもらったほうがわかりやすい。早く言うと、これは 一, ..., 九をleafとするCompositeになっている。Compositeとはいっても動的型付けだ。GoFのものと違って必ずしも継承関係はない。Duck Typingの好例となっていた。

自由演技では、ActiveScriptRubyを使って、Adobe Illulstratorのプラグインとして漢数字電卓を実現した。漢数字式を評価しながら、Illustratorの機能により漢数字が回転する。曰く、Squeakへの挑戦とのこと。

sf

こちらは自由演技のみだった。

sf 、聞いたことがあるようなないような。これはsfという計算処理系なのだな。すべての変数をカレントディレクトリにファイルとして自動的に保存するという仕様がなんか独特だ。数学定数も物理定数もファイルとして定義されている。ベクトルも扱える。LLでハミルトニアンなんて耳にするとは思わなかった。

単体で使うものではなくて、Pythonから呼んだり結果ファイルをgnuplotに送ったりして、数値解析の補助として計算処理部分に使うためのものらしい。

Squeak

これも実にSqueakらしい。 規定演技では、SqueakSmallTalk処理系がSmallTalkで書かれていることを利用して、そのソースを改造して漢数字電卓としての機能のみを持つミニ処理系を作ってしまった。資料は KanjiDentakuSqueak.zip

そして、自由演技では逆にそのコードをSmallTalk処理系に組み込んでいた。最早、Squeak環境そのものがアラビア数字表記と同じように完璧に漢数字をサポートする。ファイルから漢数字文字列を読み込んで、それにメッセージを送ると計算される。そのまま回転もする。

何というか、Squeakだ。