本を読む

読書やコンピュータなどに関するメモ

「ヴィンランド・サガ」6巻



 …のちのクヌート1世である、って感じの展開。幸村節だねぇ。

「無限の住人」23巻



 大カチコミ編。

日本Ruby会議2008に参加しました

 日本最大のRubyイベントである日本Ruby会議2008(RubyKaigi 2008)に参加しました。

 とても楽しかったけど、直後から1週間風邪で熱出してダウンしてました。そういえば当日も体調よくなくて、基調講演ほかおいしいセッションを聞き逃してしまいました。

 いまさら感はありますが、帰ってブログを書くまでがイベントのことなので、会場でとったメモをこっそり載せます。ざっとしたメモなので、間違いがありましたらご指摘ください。

 これを終えたら、ニコ動やほかの方々のレポートを見よう。

全体

 正直つくばは遠かったけど、それにみあうだけの立派な会場と仕切り。街もきれいなところだった。ちなみに、会場の隣のショッピングセンターにラーメンの青葉があったのも収穫。

 メインホールと多目的ホールに分かれて開催。多目的ホールは展示会場も兼ねていて、企業や団体のほか、ジュンク堂さんの書籍販売もやっていて、各版元(オライリー、技評、翔泳社)の方々が手伝っていた。

1日目

Ruby M17N(成瀬ゆい氏、Martin J. Dürst氏)

 Ruby 1.9のM17N(多言語対応)についてのセッション。親子ほど年の離れたコンビがうまくかみあっていたと思う。Dürst氏いわく、「Rubyを使うと若くなる」と。

 Ruby 1.9ではM17Nをサポートしている。これは、CSI(Code Set Independent)方式ということで、内部エンコーディングを決め打ちしない方式をとっている。Stringオブジェクト単位でエンコーディング情報を持っている。単なるバイト列であるASCII-8bitというエンコーディングも用意している。あと、ISO-2022-JPのようなステートフルなエンコーディングは、名前だけを知っているDummy Encodingとしている。

 で、Character Objectはない(大クラス主義)とか、文字リテラルやString#[]はRuby 1.8では整数だけど1.9ではStringになるとか、同じエンコーディングとだけ比較・結合ができる(ただしASCII文字列とASCIIを含むエンコーディングならいいらしい)とか。あと、$KCODEはobsoleteでMagic commentで指定しようとか、-Kオプションは健在とか、openの引数でencodingを指定とかいう話だった。

 Martin Dürst氏は、エンコードを変換するString#encodeライブラリを紹介。ソースファイル名とかはtranscodeとなっているけど、Matz氏の強い要望で「encode」という名前になったとか。

 処理としては、UTF-8を変換のハブとして採用。最初は1文字ごとにテーブルを作っていたけど、メモリ効率が悪すぎるので、文字コードから種類を引くテーブル(offsets)と、種類から実際の処理を引くテーブル(infos)の2つにした。オプションは:invalidと:ignoreしかないので増やしたい(ささださんの講演で9月までと期限を切られたのだとか)。

 それらを受けて、成瀬氏が、「Encodingを意識しよう」「Encoding独立なコードを書こう」「Magic Commentを書こう」とまとめていた。あと、課題では、Dirなどの対応が議論中だとか。

 という本題以上に、Q&Aセッションはコミッターの人たちを交えた激論になっていて面白かった。

  • Q: Cygwinは?
    • 最近よくなっている
  • Q: はまりどころと、具体的な対策は?
    • バイト列と文字列を連結するようなコードはエラー
    • とりあえず-Kオプションで試して、うまくいったらMagic Commentで
    • 例外が起きたら地道につぶす
  • Q: Magic CommentがRdocでそのまま出てしまう
    • Rdoc直しなはれ(笑)
  • Q: \文字コードで書かれた正規表現リテラルのエンコーディングは?
    • Script Encoding
    • US-ASCIIのアッパーコンパチ
  • Q: たとえばUTF-8なスクリプトでEUC-JPテキストを読み込んだときにマッチさせる正規表現は?
    • 変換してマッチすることになると思う
  • Q: Win32OLEは内部でUnicodeに変換している。今後は自動で変換させないようにするのか、自分でやるのか
    • 最近Direntryに関して議論があった
    • 自動変換はよくないという方向
    • デフォルトをどうするかはまた別
  • Q: ライブラリ内で日本語リテラルを書く必要がある場合、どうするのがよいか
    • いろいろやりかたがある
      • とりあえず変換
      • 正規表現
    • 受け取ったのと同じエンコーディングで返すのが定石
      • 一般的なものは難しい
      • オプションで渡す?
  • Q:normarize/denormarize(「が」→「か゛」、など)
    • やらなくちゃならないとは思っている
    • 予定には入っている
  • Q: パフォーマンスがよくなさそうだが(table lookupのキャッシュミスなど)、チューニングは?
    • 最高速ではないが、まあまあ
    • Ruby自体もそんな感じ
  • Q: どのぐらい固まったか
    • コアはだいたい固まった
    • 外縁部はつみのこしが(Dirとか)
  • Q: まとまった資料は?
    • この発表のスライド

Rubyを教えてるんじゃない、Rubyで教えてるんだってば(増原英彦)

 東大の教養学部で、情報科学の概念(計算量や動的計画法など)を教えるのにRubyを使っているという話。

 2000年ごろをさかいにComputer Scienceの人気が落ちているというのをグラフで紹介。そうした道には、いままで(日本では)ハッカー系(プログラミング大好きな人)の人が集まっていた。が、それ以外の人を増やす必要がある、ということで、記述が面倒なJavaとかより、Rubyを使っているという話。

 で、ソートのサンプル(選択ソートだったかな)を表示。イテレータやメッセージ呼び出しなどのRubyらしい文法は(最初は)使わず、昔でいうPascal的な使い方をしている。

 Rubyでよかった点は、多倍長整数がシームレスに使える点や、複数のアルゴリズムを比較するのにベンチマークやグラフ化のライブラリが揃っている点など。あと、悪いアルゴリズムでてきめんに遅くなる(笑)

 ほか、学生がハマったところとして、end忘れでエラーが出るんだけど悪い箇所が最初わからない( 学生さんはインデントしてくれない)とか、自作ライブラリが標準ライブラリと同じ名前にしたのでロードされていなかったとか、「"」やインデントが全角空白だったとか、いったエピソードを笑いの中で紹介していた。

成功するRuby教育のプラクティス(吉田裕美)

 社内でRuby開発者を増やす方法を紹介。いわく「自分が教えるのがいちばん」。会社や部署の特徴がいかせるし、アフターフォローもできる。社内に勉強する文化が生まれる。実は講師が一番勉強になる。

 具体的には、実習をペアプログラミングでやっている。ふつうの実習だと考え込んで止まってしまう人がいるけど、ペアプロなら2人が議論するので、考え込んでいる暇はない。で、スキル差を吸収できるし、実習時間が長くならない。

 あと、TDDをうまく利用。テストコードを書くのは難しいので、講師側でテストコードを与えてコードを書かせる。これで達成感(ゲーム感覚)があるし、最後にしっかりくみあわさって動くのが楽しい。

 そのほか、ほかの言語の良書をRubyのテキストとして利用してもいいじゃないかという話もあった。

 シメは、「教育は場数だ!」ということで。

RSpecによるRailsアプリケーションBDD事例報告(Yugui)

 デスマな現場にRspec駆動開発を導入して改善して乗り切った体験談。

 状況としては、機能追加、毎日バグが出る、テストされていないコード。初期対応としては、Subversion&Tracの導入(デザイナーさんも)、BuildとDeployの自動化、モジュールごとのさしかえ、Seleniumという策をうったが、それだけは足りずにやめた。具体的には、上からの加速要請や、日々出るバグ、複雑怪奇な依存関係など。

 で、Railsでさしかえることにした。で、1か月後のイベントでリリースするのに加え、仕様や構成は試行錯誤となるため、柔軟さが必要。Seesar2も検討したが、中身まで知っているということでRailsを採用した。Seleniumdeで記録した資産を活用し、正常系と異常系のふるまいを規定してRspecによるBDDに落とし込んだ。

 フェーズ1は2人。最初はSpecのカバレージ低め。フェーズ2で4人に増えてまわりに浸透、Specのカバレージが増えてSpecがコードの7割になった。ここで1か月。フェーズ3は機能追加やメンテのフェーズで、みんなで取り組んだ(が、会社がなくなった)。

 まとめとしては、「ペアプロによる勇気」「動的型のリスクはBDDで排除できる」と。

質疑応答では、「テストを書く暇があったらコードを書け」と上司に言われる場合は? という質問に対し、「わからんやつは黙ってろ」と答えた(会場笑)という名言が生まれた。

Ruby技術者認定試験模擬問題解説

 ここで多くの人が多目的ホールへ移動したけど、試験ネタも興味あったのと、体調もいまいちだったので引き続きメインホールで。

 問題としては、真になる値はどれ、みたいなRuby独自の挙動を問うものが多いようだ。で、舞台横のIRC画面を見ていると、コミッターの方々が、あーこの仕様残ってたんだ、変えちゃいたい、みたいな話をしていて、よくも悪くも仕様が安定しないなぁ(笑)と思った。

LT:JavaからRubyについて、どうしても言いたいことがある(kuwata)

 ここからライトニングトーク。

 1人目はTenjinの人らしい。Rubyを教えるのに初級者偏重は大間違いで、Javaは初級者向け、Rubyは上級者向け、上級者に足かせをするな、との話。

LT:dRubyとセキュリティ(西山氏)

 drubyを不特定多数に向けて公開するのは危険というのとで、method_missingで充分な例、禁止されているメソッド、$SAFEをあげて制限などの例を上げていた。

RubyとODEでピタゴラ装置(佐々木氏)

 3D CGの空間による異色のプレゼン。3D描画ライブラリODE+Ruby Cocoaで、Wiiリモコンを使って操作していた。

 スライドがわりの物体の背後で大きなピタゴラ装置が動作していて、後半はそのピタゴラ装置の実演。場内拍手喝采で盛り上がった。

初級者はEnumeratorの夢を見るか?(いまい氏)

 Ruby初級者はeachを使いたがるけど、each_sliceとかeach_consも便利だよ、最近はブロックなしのEnumerableなメソッドがEnummeratorオブジェクトを返したりもするよ、という話。

Folk Programming with Ruby(mootoh)

 Folk Songみたいな気軽さで、Webアプリ以外で楽しいプログラミングをやろうという話。

 具体的にはPlug-in作りで、いちから使うより簡単、使ってもらいやすい=ハードルが低いという。

実例として、Safari+はてブ管理GUIとか、QuickSilver+Twitter、Quartz Composer+Gainer、Vim+Refeを紹介していた。

Ruby.pm(藤氏)

 Rubyと同じ処理をPerlの文法の中で扱うPerlモジュールRuby.pmを紹介。RubyのeachをPerlの文法で表現したらこうなるよなぁという記述。Perlの関数をRubyなメソッドから実行したりもできる。

toRubyで見つけたRubyist人生再出発(いけざわ氏)

 toRubyはtochigi Rubyの略。おじさんプログラマーがRubyのOOPがわからなくて教えてくれる人がほしいと思ったときに、勉強会開催にこぎつけるまでの熱い体験談。全会場が泣いた!

Ruby 1.9 on Rails 2.1(松田明)

 Web+DBシステムは、プログラム中に生SQL→O/Rマッパー→ActiveRecordと進化してきた。でも、「15分で作るブログ」みたいなアプリだったらいいけど、実はDBアクセスはRailsの弱点という話。

 で、Rails 2.1からnamed_scopeが導入されて、関係代数(集合演算)を表せるようになったというのを紹介した。

テストベースコードリーディングのすすめ(遠藤氏)

 新人Rubyコミッタの人。ソースコードリーディングにはテストを書くのがいいということで、テストが充実していなかったRubyのソースをテストカバレッジ測定ツールにかけ、実行されていない部分をカバーするテストを追加して勉強していたという話。

 その結果、ほかのP言語をおさえてテストのカバレッジが85%に上がった。いまも毎晩自動でカバレッジを測定しているのとこと。

A Jail Web Development with Rails 2008 でわっふるわっふる(竹迫氏)

 「Ajile」じゃなくて「A Jail」だよ、という話を枕に、YAPC::Asiaで紹介していたmod_waffulを簡単に解説。テスト版は公開中、正式版はパフォーマンスチューニングしてから公開とのことだった。

Industrial-Designed Language: Ruby(斎藤ただし)

 パソコンが調子悪いとのことで、スライドなし、しゃべりのみのプレゼン。っていうかもともとスピーチってそういうものだったかも。

 Rubyは工業デザインとしてすぐれている、たとえば驚き最小の原則=アフォーダンス、ということを熱く語った。で、最後は、Matzの屍を越えて(え?)よりよい言語を作ろう、というまとめに。

2日目

REST信者から見たRuby on Rails 2.x(山本陽平氏)

 RubyのMLでは早くからRESTに注目していて、RubyとRESTはなかよし。また、RailsとRESTはなかよし。

 という話をマクラにWebのアーキテクチャスタイルのRESTを解説。

 RESTの要件は、全部準拠しなくてはならないものではない、という話が力点が置かれていた。アドレス可能性がいちばん重要で、次に接続性。ステートレス性はあまり重要じゃない、Cookie使わないなんてありえない(山本説)という話だった。

 アドレス可能性は、リソースを定義してそれにアドレスを与えること。URIの設計をしてからURIの実装するというURI駆動開発を、Rails、Restlet、Djangoでのそれぞれの例で紹介した。

 接続性は、アプリケーション状態エンジンとしてのハイパーメディア。つまり、ページ遷移=状態遷移として設計するという、リンクの設計。Railsでいうと、url_forやlink_toだが、リンクの意味を意識できればもっといい(aのrel属性などの意味づけ)とのことだった。

 最後は、実際のところRailsはRESTfulである、初心者がチュートリアルどおり作るとRESTfulになる、という話でまとめてた。

  • Q: 考え方を切り替えるコツは?
    • A: ぜんぶリソースで考える
  • Q: 確認画面はRESTfulでありえるか
    • A: それは本当にサーバーサイドでやらなくてはならないのか。クライアントサイドでいいじゃないか。
  • Q: ステートレス性とユーザーの認証状態はどう組み合わせるか
    • A: ふつうにみなさんがやっているように処理すればいいのでは。ステートレスを考えすぎると処理が重くなるだけ。

Real-World Enterprise Ruby(大場さん、高井さん)

 CTCというスーツなSIerでいかにRubyを導入したかという体験談。Ruby案件で売上4.5億とか。

 実際にスーツ姿で登壇して、交互にしゃべってボケ・ツッコミっぽい役割分担、ダイナミックな動きなど、スーツというより漫才かも(笑)。

 まず、エンタープライズって何? ということで、規模や人数ではない、企業の業務の一部であること、と。

 その中にRubyを持ち込んだときには、きちんとRubyを自社内で位置付けて、どうやって会社の利益に貢献するかを会社に説明した。つまり、Rubyをキメると楽しくなる、生産性が高い、というだけでだめだったので、新規顧客・案件の獲得(いままで取りこぼしていた案件をとる)というのを説得材料にした。つまり、JavaからRubyじゃなくて、Javaに加えてRuby、と。

 技術部門には、保守・運用フェーズでのサポートを容易。営業部門には、営業向けの提案資料にコピペできる資料を用意。実績面では伊藤忠ウェブテクノロジーラボで武者修行、見積りにはJavaと同じ手法を用意、開発者はCTCテクノロジーでトレーニングや認定試験、技術支援にはコードレビューやトラブルの逐次対応、開発環境にはNetBeans 6推奨、運用環境としてはハードウェアやミドルウェアごとに検証センターで基礎データを収集。

 と、必要なものをすべてお膳立てして、想像ではなくデータで回答することが重要だったという話だった。また、松江好きの役員が後押ししてくれたという裏話もあった。

 Q&Aでは、営業資料の素を公開できないかという声もあったが、FP値とか入っているので難しいとのことだった。

net-ircというモジュールの実装紹介(cho45)

 サブテカのcho45さんのセッション。

 irc大好きで、なんでもircに集約している、そこでnet-ircというライブラリを作ったという話。実装はRICEベースなのだけど、RICEはRFC準拠しすぎて使いにくい(UTF-8、nickname長など)、Observerパターンを使っていてオーバーヘッドがある、などから作り直した。

 実際に、Net::IRC::Clientを継承して簡単なクライアントを作る例や、Net::IRC::Server::Sessionを継承して簡単なサーバーを作る例を紹介していた。また、作ったアプリケーションとして、ミニブログ-IRCゲートウェイ、Lingr-RCゲートウェイ、mixiに投稿などを紹介した。

 で、IRC用botがほかで使えるという長所を語ったあと、Citrus IRC bot frameworkのプラグイン機能の話を経て、後半はDSL論を展開した。

 いわく、DSLは濫用しない、と。たとえばscrAPIは引数の意味がわからなくてリファレンスが必要なので悪い例。RakeやRSpecは、ぱっと見でわかり、見よう見真似で使えるからOK。Test::Unitはわからない。ほかにも、DSLはブロックがどこで実行されるのかトレースしづらいうというのも濫用してほしくないところ、と。最後は「高度に発達したDSLは新言語と見分けがつかない」ということばで締めた。

Rubyプログラムの型推論(松本宗太郎)

 Rubyプログラムの型推論をするソフトを開発した話。ちょうど公開したところだったとか。

 型宣言はなく、ダックタイピングやオープンクラス、動的機能(evalとか__send__とか)、拡張ライブラリを持つというRubyの特徴を生かした。型宣言は追加せず、NoMethodErrorなどのランタイムエラーになるプログラムをrejectする。

 実装には、MLの型推論アルゴリズムのunificationや多相レコード型を採用した。この方法のほかには、フロー解析という方法もある(静的アナリシス)。

 Reflectionやevalの対応は無理で、しかたなく型注釈を入れることを考えている(これから)。

 ほか、Polymorphoic Methodsとか、型の違う要素が並んだ配列のmapとか、ループ中で、Integerを期待する変数に文字列を入れた場合とか、うまくいかないところがあるけど、がんばりすぎず、例外をトラップすればいいと考えている、と。

 あと、lambdaにブロックを与えないで呼び出すと外のブロックを引数とするという仕様は頭が痛いのだけど、推奨されていないのでほっとした、という話。

CRubyのGCをどげんかせんといかん(authorNari)

 JRuby、Rubinius、CRubyのGC方法を比較して、どげんかせんといかん、という話。

 プロセスメモリサイズの肥大化の問題として、ヒープ配列が足りなくなると増設していくけどオブジェクトが残っていると開放できないのでスカスカのヒープ配列が増えていくという問題。これは、配列を小さくするパッチを書いて、1.9-2に採用、と。ただし、Q&Aによると、スループットのパフォーマンスは若干落ちたとのこと。

 次に、stop-the-world問題。イタリア人の兄弟が飛び跳ねるゲームを黒塗りで移して、GC中にレスポンスが止まるところを実演。会場にいた小さな子が「○リオだー!」と声を上げていた(笑)。で、markは一度にやるけどsweepは少しずつやるというLazySweepのパッチを書いたけど、まだ取り込まれていないという紹介。

 これからやりたいこととしては、BoehmGC採用とか、thread localなフリーリストならキャッシュが効くか、とか、incremental GCもやりたいけどwrite barriorが難しいとかいう話だった。

SVuGy: SVGと遊ぼう (Martin J. Dürst氏)

 SVuGyはSVG+Rubyで、SVGを扱うDSL。SveeGeeと発音する。現在0.03で、zipとtar.gzで配布している。ver 0.4も近日公開予定、と。

 もともと授業用に図を簡単に作れるようにという実利と、手続き型と宣言型の変換の研究、Rubyの勉強ということから始めた。

 単純な記述は「rect 100, 200, 30, 50」みたいに書ける。その他、ブロックでグルーピングとか、スタイルをハッシュ/ブロック/メソッドチェーンの3種類で書けるとか、constant_missingでquoteされていない色属性をつかまえるとか、SVGのidをmethod_missingで処理したりとかの機能を紹介。やりすぎかどうか意見を聞きたいとのことだった。

 0.4の新機能としては、SVGをよりサポート、pathなどのオブジェクト、別のオブジェクトに属する点を結ぶ線をきれいに、SVGの読み込み(REXML利用)、いろいろなオブジェクト、レイヤーのサポートとのこと。これはら、レイアウトやAPI、制約、グラフ描画などの高レベルライブラリに取り組みたいとのことだった。

閉会式

 元祖高橋メソッド。2009年はYAPCを見習って多言語化(英語とか)を目指したいとのこと。そして、全国各地で地域Ruby会議を開きたい、という話も出た。

RejectKaigi、RejectRejectKaigi

 LTであふれたネタ大会RejectKaigiがさらにあふれたので、RejectRejectKaigiも開催。しかも同じ部屋で、ひとつのタイムキーパーで同時進行という無茶さ。さらにステージ横で「Railsレシピブック」のサイン会も開かれ、テラカオス。すごく盛り上がった。

 以下、細かいところはわからいけど、メモした範囲で一気に(敬称略)。

  • 3の実装の時にアホになるRuby(yoshiori)
    • 昨日Rubyはじめました。Rubyも入れました
    • 数字をカウントするRubyスクリプトをそのままJRubyで動かしたら日本語になった!
  • Rest In Peace 1.8.5(占部)
    • 1.8.5はexpired
    • patchlevelの推移
  • Redmine Ruby 1.9.1(yugui)
    • Ruby 1.9開発のプロジェクト管理
    • データ移行中
    • スタッフ募集中
    • 1.9.1は、Sep.25にfix、Dec.25にrelease予定
  • 私はDecimalで何をしようとしているか(斎藤ただし)
    • あいかわらずパソコンの調子が悪いということで、ノートパソコンの画面を直接会場に見せるプレゼン
    • Big Decimalがださすぎるので、Decimalとして再実装した
    • Decimalの歌
  • ひとばんでつくるRuby + Greaseonkey (さとうたかよし)
    • Creamというのを作ったら、アメリカ人に「名前がひどすぎる」と言われてGreaseKitにした
    • Objective-Cで書いた。大括弧が多い
    • Rubyで書き直したGreaseKit Red
  • Remaze(?)
    • Communityが強い
    • バグは48時間以内に直す
  • Award on Rails 2208(?)
    • 自分も出ます
    • おまけ:ぽろりシミュレータ
  • 変なサービスができるまで(星暁雄)
    • 梁山泊的なものを追いかける
    • コモンズマーカー
      • ソーシャルコメント
      • アノテーション
      • ミニブログ
    • 開発者募集中
  • Gauche on Rails(yumm3)
    • メタプログラミングといえばLisp
    • scaffold
    • テンプレートにS式
    • コントローラで継続
    • よいRubyコードをかくにはLispの知識が必要
  • Reposh(yhara)
    • ハッカーのためのリポジトリシェル
    • 怠惰なので実演
    • 何度もsvnって
  • Hash::mapがあふぉーだんすに優れていない件(ミムラ takkam_m)
    • Hash::mapの結果がarrayになる
    • mapは写像なはず
    • HashからHashを生成するmaph
  • String#succ(?)
    • matzを266760647回succするとnakada
    • 元.succで兄
    • 美から鼻
    • encoding validation
  • 私はいかにしてRubyKaigiを私物化したか(ただ)
    • バッグがほしいのでノベルティをトートバッグに
    • どこに行っても同じトートバッグを見かけるにはちょっと→スタンプ式
    • iDiary.netでニコ動外部プレイヤーを使えるようにした
    • 毎日5時に起きてニコ動を見ている
  • beeptoys(takkaw)
    • ビーブ音源で音楽
  • RubyでIdenticon(swdyh)
    • AutoPagerizeの人
    • IPアドレスからアイコンを生成
    • IPアドレス以外に、ドメイン名、ユーザーID、OpenIDのURLなど
    • Rubyの実装がなかったので作った「quilt」
    • RMagikかGDが必要
    • 最新版はgithub
  • Illustratorで高橋メソッドプレゼンツール(?)
    • Win32OLE
    • エフェクト
    • 計算もできる
    • 写真も置ける
  • infix to postfix again(shinh)
    • evalで中置き記法を
    • method_missingをprintにalias
      • _メソッドがmethod_missingになる
  • tDiaryとHikiで使うフィルタ(黒田ひらく)
    • スパムフィルタ
      • 人間が確認
  • Rubyでつくろう二次元プログライング「ず」(naoya_t)
    • 有向グラフ
    • brainfuckライブラリ(coderepos)
  • NDD - Niconico Driven Developlent(井上泰行)
    • とにかく作る
    • ニコニコにup
    • コメントがつく
    • やる気になる
  • YARVをしのんで(ささださん)
    • Nadokaをしのんで
      • だれかメンテして
      • net-ircよさそうですよね
    • Rabbitをインストールできませんでした
    • 学生募集中、じゃなくて
    • VMで1.9が高速化されました、じゃなくて
      • 一部しか入っていない(バグってるから)
    • VMの導入はゴールじゃなくてはじまり
      • いろいろなことをやるためのプラットフォームとしてのRubyVM
  • TechTalk.jp(coji)
    • IT勉強会多い
    • 動画で
  • Rubyバイトコードで遊ぼう(赤井俊平)
    • ソースからバイトコードにコンパイル
    • VM::InstructionSequence.compile('...')
    • rb.comple.to_a:
    • メソッド書き換えをやろうとしてloadのバグを発見
  • KaigiFreaks(?)
    • 動画配信
    • 地方RubyKaigiに応募
      • 「Ruby札幌が釣れました」
  • ?(cho45)
    • Rdocのテンプレートを直接作るな
    • resh
    • require 'future'
      • 重い処理を非同期に
      • r = f.async.omoi(1);nil
      • rを参照したときに待ち
  • やる夫で学ぶJRuby最適化(高井)
    • いつリリースされるかわからない1.9よりJRubyだお
    • サーバVMを使って最適化
    • バイトコンパイル
    • おそくなってやがる

Regional RubyKaigiのご提案(角谷)

 RejectKaigi枠だったけど、単独でメモ。

 RubyKaigiのふりかえり。KEEPは、RubyKaigiブランド確立、さまざまな成果物や会合、さまざまなチャレンジ。一方PROBLEMは、規模の拡大、運営負荷の増大、継続可能性。

 これからのTRYは、RBAとの密な連携、Ruby Centralとの連携、継続可能な枠組み。

 Reject会議大もりあがり、もっとKaigiを、ということで、「我が名はレギオン」「邪神覚醒」というわけで、Regional RubyKaigi。早めに、こまめに。

 まずは自分がやってみせたいので、第1回は東京。メンバー募集中。RubyKaigi本編とちがってゆるふわで。待デ続報!

 角谷さんのブログを拝見すると、Shibuya.pm Technical Talkみたいなのをイメージしてるみたい。

「初めてのRuby」

初めてのRuby
初めてのRuby
posted with amazlet at 08.06.22
Yugui
オライリージャパン
売り上げランキング: 4611


 日本Ruby会議2008で買い、帰り道で読了。

 プログラミング初心者向けではないRuby初心者に向けて、リファレンスでもクックブックでもない形式で、Rubyの特徴的な部分を解説する本。特に、ブロック引数/イテレータや、ダックタイピング、特異メソッド/特異クラス、継承、メタプログラミングあたりに著者が特に注力している感じがして、面白かった。

 あと、細かいけど実用的な部分について、Ruby 1.9と1.8の違いを併記していたりするところが、Ruby初学者じゃないけど初級者な自分にとって参考になった。

「喰いしん坊!」19巻



 喰いワンGP決勝戦、ついに決着! そして舞台は世界に。

 それはさておき、p.92の「未知の外国人」の描写があまりに昔のステロタイプすぎて、吹いた。

Rubyで文字列を桁数で切り詰める

 メールや端末へ出力するときに、文字数でもバイト数でもなくて、桁数で文字列を切り詰めることがあります。というか最近ありました。先頭から60桁で切る、とか、固定幅テキストで表を表す、とかいう話です。

 「桁数=バイト数」という前提が許されるのは昭和までですが、仲間うちのRuby on Railsアプリで桁数切りをやろうとして悩みました。

 もっと簡単な方法がありそうな気がしますが、プログラミング初級者がハマったメモとして残しておきます。簡単な方法があったら教えてえらい人。

 以下、Ruby 1.8+UTF-8環境での結果です。

うまくいかない例:正規表現とかprintfとか

 正規表現の繰り返し制御は、$KCODEが'NONE'の場合はバイト数で、'u'の場合は文字数でマッチするみたいです。

irb(main):001:0> 'あいうえお'.sub(/^(.{3}).*/, '\1')
=> "\343\201\202"
irb(main):002:0> $KCODE='u'
=> "u"
irb(main):003:0> 'あいうえお'.sub(/^(.{3}).*/, '\1')
=> "あいう"

 桁で切るために、一度EUCにして処理し、あとでUTF-8に戻すという方法も考えました。が、これだと、マルチバイト文字の途中に切れ目がある場合、文字の途中で切ってしまっておかしな結果になります。

irb(main):001:0> $KCODE = 'NONE'
=> "NONE"
irb(main):002:0> 'あお'
=> "\343\201\202\343\201\212"
irb(main):003:0> 'あお'.toeuc.sub(/^(.{3}).*/, '\1').toutf8
=> "\352\222\242"

 ちなみに、sptintf(printf)や%演算子は、$KCODEにかかわらずバイト数で切るようです。

irb(main):001:0> printf '%.4s', 'あお'
あ�=> nil

頭から数えて解決

 いい方法が思いつかなかったので、文字列の頭から数を数える単純な方法でメソッドを作ってみました。

class String
  def truncate_column(col)
    count = 0
    ary = []
    self.split(//u).each {|c|
      count += (c.size == 1 ? 1 : 2)
      return ary.join('') if count > col
      ary.push(c)
    }
    self
  end
end

 「半角カナ入力禁止」が許されるのも昭和までかもしれないので、いわゆる半角カナに対応してみます。

class String
  def truncate_column(col)
    count = 0
    ary = []
    self.split(//u).each {|c|
      if (c.size == 1) ||
         (/[。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚]/u =~ c)
        count += 1
      else
        count += 2
      end
      return ary.join('') if count > col
      ary.push(c)
    }
    self
  end
end

日本語だけじゃなく

 といっても、UTF-8でマルチバイトの文字は、半角カナだけじゃありません。そこで、UAX#11のEast Asian Width属性を参照して全角半角を決めてみます。

 …えーと、こんなんなっちゃいました。

class String
  RE_UAX11_H = Regexp.new("[#{[8361].pack('U')}
    #{[65377].pack('U')}-#{[65500].pack('U')}
    #{[65512].pack('U')}-#{[65518].pack('U')}]", Regexp::EXTENDED, 'u')
  RE_UAX11_Na = Regexp.new("[#{[162].pack('U')}-#{[163].pack('U')}
    #{[165].pack('U')}-#{[166].pack('U')}
    #{[172].pack('U')}
    #{[175].pack('U')}
    #{[10214].pack('U')}-#{[10219].pack('U')}
    #{[10629].pack('U')}-#{[10630].pack('U')}]", Regexp::EXTENDED, 'u')
  RE_UAX11_N = Regexp.new("[#{[128].pack('U')}-#{[160].pack('U')}
    #{[169].pack('U')}
    #{[171].pack('U')}
    #{[181].pack('U')}
    #{[187].pack('U')}
    #{[192].pack('U')}-#{[197].pack('U')}
    #{[199].pack('U')}-#{[207].pack('U')}
    #{[209].pack('U')}-#{[214].pack('U')}
    #{[217].pack('U')}-#{[221].pack('U')}
    #{[226].pack('U')}-#{[229].pack('U')}
    #{[231].pack('U')}
    #{[235].pack('U')}
    #{[238].pack('U')}-#{[239].pack('U')}
    #{[241].pack('U')}
    #{[244].pack('U')}-#{[246].pack('U')}
    #{[251].pack('U')}
    #{[253].pack('U')}
    #{[255].pack('U')}-#{[256].pack('U')}
    #{[258].pack('U')}-#{[272].pack('U')}
    #{[274].pack('U')}
    #{[276].pack('U')}-#{[282].pack('U')}
    #{[284].pack('U')}-#{[293].pack('U')}
    #{[296].pack('U')}-#{[298].pack('U')}
    #{[300].pack('U')}-#{[304].pack('U')}
    #{[308].pack('U')}-#{[311].pack('U')}
    #{[313].pack('U')}-#{[318].pack('U')}
    #{[323].pack('U')}
    #{[325].pack('U')}-#{[327].pack('U')}
    #{[332].pack('U')}
    #{[334].pack('U')}-#{[337].pack('U')}
    #{[340].pack('U')}-#{[357].pack('U')}
    #{[360].pack('U')}-#{[362].pack('U')}
    #{[364].pack('U')}-#{[461].pack('U')}
    #{[463].pack('U')}
    #{[465].pack('U')}
    #{[467].pack('U')}
    #{[469].pack('U')}
    #{[471].pack('U')}
    #{[473].pack('U')}
    #{[475].pack('U')}
    #{[477].pack('U')}-#{[592].pack('U')}
    #{[594].pack('U')}-#{[608].pack('U')}
    #{[610].pack('U')}-#{[707].pack('U')}
    #{[709].pack('U')}-#{[710].pack('U')}
    #{[712].pack('U')}
    #{[716].pack('U')}
    #{[718].pack('U')}-#{[719].pack('U')}
    #{[721].pack('U')}-#{[727].pack('U')}
    #{[732].pack('U')}
    #{[734].pack('U')}
    #{[736].pack('U')}-#{[767].pack('U')}
    #{[884].pack('U')}-#{[912].pack('U')}
    #{[938].pack('U')}-#{[944].pack('U')}
    #{[962].pack('U')}
    #{[970].pack('U')}-#{[1024].pack('U')}
    #{[1026].pack('U')}-#{[1039].pack('U')}
    #{[1104].pack('U')}
    #{[1106].pack('U')}-#{[4348].pack('U')}
    #{[4448].pack('U')}-#{[8207].pack('U')}
    #{[8209].pack('U')}-#{[8210].pack('U')}
    #{[8215].pack('U')}
    #{[8218].pack('U')}-#{[8219].pack('U')}
    #{[8222].pack('U')}-#{[8223].pack('U')}
    #{[8227].pack('U')}
    #{[8232].pack('U')}-#{[8239].pack('U')}
    #{[8241].pack('U')}
    #{[8244].pack('U')}
    #{[8246].pack('U')}-#{[8250].pack('U')}
    #{[8252].pack('U')}-#{[8253].pack('U')}
    #{[8255].pack('U')}-#{[8305].pack('U')}
    #{[8309].pack('U')}-#{[8318].pack('U')}
    #{[8320].pack('U')}
    #{[8325].pack('U')}-#{[8360].pack('U')}
    #{[8362].pack('U')}-#{[8363].pack('U')}
    #{[8365].pack('U')}-#{[8450].pack('U')}
    #{[8452].pack('U')}
    #{[8454].pack('U')}-#{[8456].pack('U')}
    #{[8458].pack('U')}-#{[8466].pack('U')}
    #{[8468].pack('U')}-#{[8469].pack('U')}
    #{[8471].pack('U')}-#{[8480].pack('U')}
    #{[8483].pack('U')}-#{[8485].pack('U')}
    #{[8487].pack('U')}-#{[8490].pack('U')}
    #{[8492].pack('U')}-#{[8526].pack('U')}
    #{[8533].pack('U')}-#{[8538].pack('U')}
    #{[8543].pack('U')}
    #{[8556].pack('U')}-#{[8559].pack('U')}
    #{[8570].pack('U')}-#{[8580].pack('U')}
    #{[8602].pack('U')}-#{[8631].pack('U')}
    #{[8634].pack('U')}-#{[8657].pack('U')}
    #{[8659].pack('U')}
    #{[8661].pack('U')}-#{[8678].pack('U')}
    #{[8680].pack('U')}-#{[8703].pack('U')}
    #{[8705].pack('U')}
    #{[8708].pack('U')}-#{[8710].pack('U')}
    #{[8713].pack('U')}-#{[8714].pack('U')}
    #{[8716].pack('U')}-#{[8718].pack('U')}
    #{[8720].pack('U')}
    #{[8722].pack('U')}-#{[8724].pack('U')}
    #{[8726].pack('U')}-#{[8729].pack('U')}
    #{[8731].pack('U')}-#{[8732].pack('U')}
    #{[8737].pack('U')}-#{[8738].pack('U')}
    #{[8740].pack('U')}
    #{[8742].pack('U')}
    #{[8749].pack('U')}
    #{[8751].pack('U')}-#{[8755].pack('U')}
    #{[8760].pack('U')}-#{[8763].pack('U')}
    #{[8766].pack('U')}-#{[8775].pack('U')}
    #{[8777].pack('U')}-#{[8779].pack('U')}
    #{[8781].pack('U')}-#{[8785].pack('U')}
    #{[8787].pack('U')}-#{[8799].pack('U')}
    #{[8802].pack('U')}-#{[8803].pack('U')}
    #{[8808].pack('U')}-#{[8809].pack('U')}
    #{[8812].pack('U')}-#{[8813].pack('U')}
    #{[8816].pack('U')}-#{[8833].pack('U')}
    #{[8836].pack('U')}-#{[8837].pack('U')}
    #{[8840].pack('U')}-#{[8852].pack('U')}
    #{[8854].pack('U')}-#{[8856].pack('U')}
    #{[8858].pack('U')}-#{[8868].pack('U')}
    #{[8870].pack('U')}-#{[8894].pack('U')}
    #{[8896].pack('U')}-#{[8977].pack('U')}
    #{[8979].pack('U')}-#{[9000].pack('U')}
    #{[9003].pack('U')}-#{[9290].pack('U')}
    #{[9450].pack('U')}
    #{[9548].pack('U')}-#{[9551].pack('U')}
    #{[9588].pack('U')}-#{[9599].pack('U')}
    #{[9616].pack('U')}-#{[9617].pack('U')}
    #{[9622].pack('U')}-#{[9631].pack('U')}
    #{[9634].pack('U')}
    #{[9642].pack('U')}-#{[9649].pack('U')}
    #{[9652].pack('U')}-#{[9653].pack('U')}
    #{[9656].pack('U')}-#{[9659].pack('U')}
    #{[9662].pack('U')}-#{[9663].pack('U')}
    #{[9666].pack('U')}-#{[9669].pack('U')}
    #{[9673].pack('U')}-#{[9674].pack('U')}
    #{[9676].pack('U')}-#{[9677].pack('U')}
    #{[9682].pack('U')}-#{[9697].pack('U')}
    #{[9702].pack('U')}-#{[9710].pack('U')}
    #{[9712].pack('U')}-#{[9732].pack('U')}
    #{[9735].pack('U')}-#{[9736].pack('U')}
    #{[9738].pack('U')}-#{[9741].pack('U')}
    #{[9744].pack('U')}-#{[9747].pack('U')}
    #{[9750].pack('U')}-#{[9755].pack('U')}
    #{[9757].pack('U')}
    #{[9759].pack('U')}-#{[9791].pack('U')}
    #{[9793].pack('U')}
    #{[9795].pack('U')}-#{[9823].pack('U')}
    #{[9826].pack('U')}
    #{[9830].pack('U')}
    #{[9835].pack('U')}
    #{[9838].pack('U')}
    #{[9840].pack('U')}-#{[10044].pack('U')}
    #{[10046].pack('U')}-#{[10101].pack('U')}
    #{[10112].pack('U')}-#{[10213].pack('U')}
    #{[10224].pack('U')}-#{[10628].pack('U')}
    #{[10631].pack('U')}-#{[11805].pack('U')}
    #{[12351].pack('U')}
    #{[19904].pack('U')}-#{[19967].pack('U')}
    #{[42752].pack('U')}-#{[43127].pack('U')}
    #{[55296].pack('U')}-#{[56320].pack('U')}
    #{[64256].pack('U')}-#{[65021].pack('U')}
    #{[65056].pack('U')}-#{[65059].pack('U')}
    #{[65136].pack('U')}-#{[65279].pack('U')}
    #{[65529].pack('U')}-#{[65532].pack('U')}
    #{[65536].pack('U')}-#{[120831].pack('U')}
    #{[917505].pack('U')}-#{[917631].pack('U')}]", Regexp::EXTENDED, 'u')

  def truncate_column(col)
    count = 0
    ary = []
    self.split(//u).each {|c|
      if (c.size == 1) ||
         (RE_UAX11_H =~ c) || (RE_UAX11_Na =~ c) || (RE_UAX11_N =~ c)
        count += 1
      else
        count += 2
      end
      return ary.join('') if count > col
      ary.push(c)
    }
    self
  end
end

 ちなみに定数部分は、こんなやっつけRubyスクリプトで生成しました。

#!/usr/bin/ruby -Ku

PROTOTYPES = %w{ A F H N Na W }
HALF_PROTOTYPES = %w{ H Na N }

h = {}
PROTOTYPES.each {|e| h[e] = [] }

current = nil
start_n = end_n = nil

open('EastAsianWidth.txt') {|f|
  f.each {|line|
    next if /^#/ =~ line || /^$/ =~ line
    code, prop = line.chomp.sub(/ .*/, '').split(/;/)
    code.gsub!(/[\dA-F]+\.\.(\dA-F)/, '\1')
    code_n = code.hex
    next if code_n < 0x80
    if (current == prop)
      end_n = code_n
    else
      if current
        h[current].push(
          if start_n == end_n
            "\#{[#{start_n}].pack('U')}"
          else
            "\#{[#{start_n}].pack('U')}-\#{[#{end_n}].pack('U')}"
          end
        )
      end
      start_n = end_n = code_n
      current = prop
    end
  }
}

HALF_PROTOTYPES.each {|e| puts "  RE_UAX11_#{e} = Regexp.new(\"[#{h[e].join("\n    ")}]\", Regexp::EXTENDED, 'u')" }

別解

 nkfを使う方法も考えたんですが、半角カナが2桁になっちゃうんですよね。

#!/usr/bin/ruby -Ku

require 'nkf'

class String
  def truncate_column(col)
    NKF.nkf("-F#{col} -Ww -x", self).sub(/\n.*/m, '')
  end
end

puts 'あアaあ'.truncate_column(4)

修正2008-06-19: 誤ってEast Asian Width属性のA・H・Naを半角扱いするコードになっていたので、H・Na・Nに修正。

「Q.E.D.」30巻

 初期のころから「殺人事件に限らない本格ミステリマンガ」という評判があったけど、今回は帯に「今度の事件は殺人ではない、殺人!?」と。まぁ、殺人もあるけど。

 「人形殺人」は、人形が刺されていた事件に始まる連続事件。印象によるミスリーディングにやられた。

 「犬の茶碗」は、詐欺師を騙し返そうというコンゲームもの。というネタは最近いろいろあるけど、さすがミステリマンガの第一人者、かけひきがみごとに決まった。伏線もはまってる。

「C.M.B.」8巻

「貝がらを自分で拾う人」「貝がらがあることを教えてもらう人」「貝がらを見ない人」の3人がいたら…
その3人はみんな必ず こう言う
「海岸に貝がらがあることは知っている」って

 「Q.E.D.」の姉妹編で、博物学ネタのマンガ。最近はミステリー要素が増えてきているけど、より人情話のほうに比重があるように思う。

 「1億3千万人の被害者」は、復讐のために1億3千万人の被害者を出すという犯罪予告の話。論理と叙述の罠が何重にもはりめぐらされている。テーマがわりとシリアスなのだけど、トリックと不可分なのでここでは略(ヒント:アイヒマン実験)。

 「メテオライト」は、カザフスタン領のロシア宇宙センターに落ちた隕石の話。単純だけどうまいトリック。

 「櫛野村奇譚」は、ホラーっぽいファンタジー。論理を追っていくと謎が増えるのだけど、最後でつじつまが合う(ミステリー的にではないけど)。そういう意味で、「ちょっとぐらいの矛盾なんて味じゃん」にクスッと笑った。

 「牡山羊の像」は、倒叙ものと思いきや、伏線がいろいろキマっている。ちなみに、冒頭の引用は、この作品から。

OSC2008.DBに参加

 何ヶ月かぶりに週末に時間がとれたので、6月7日(土)にオープンソースカンファレンス2008.DBというイベントに参加してきた。オープンソースのRDBMSであるPostgreSQL・MySQL・Firebirdについてのセミナーイベント。

 それぞれのUpdate情報が楽しみだったのだけど、遅刻してPostgreSQLのUpdateが聞けず、MySQLも途中から。だめじゃん。

 以下、そんな範囲でのメモ。

MySQL Update(日本MySQLユーザ会 梶山隆輔氏)

 着いたときには、新しいFalconやMariaを含めた(?)ストレージエンジンの紹介と比較をやっていたような。

 ER図編集ツールのMySQL Workbenchも紹介。商用版はそのままDBのテーブルを作成、フリー版はCREATE TABLEなどのSQLスクリプトを吐く。ほか、クエリーを振り分けるMySQL Proxyとか、memcachedとの連係とか、クエリーのモニター機能とかを紹介していた。

Firebird Update(Firebird日本ユーザー会 木村明治氏)

 Firebird 2.1を紹介。大規模向けというよりは、使って便利な機能が追加されているとのこと。

  • データベーストリガ
    • CONNECTとかTRANSACTION STARTとかのDBのイベントに対するトリガ
    • 監査などに利用?
  • MERGE文
    • 対照表と差分表をMERGEする
    • MySQLでは、REPLACE文や、INSERT文のON DUPLICATE KEYを使う
  • グローバル一時表
    • セッション期間中データを保持する
  • CTE(共通表式)
    • サブクエリーにWITH句で名前をつけて、ひとつのSQL文の中で使いまわす
    • 再帰クエリにも使える
      • RDBの前の階層型DBっぽいやりかた
      • OracleだとCONNECT BY
  • モニタリング表とキャンセル
  • 64bit Windows

 で、後半は、ハードの要求レベルが低いことを示すために、Pentium 133MHzのマシンでWindows 3.1+WinSockの動かした様子を紹介して笑いをとっていた。win32sとかのネタで盛り上がるし、みんなオヤジだなぁ(笑)。

Firebirdを組み込みで使ってみよう(Firebird日本ユーザー会 加藤大受氏)

 Firebirdの特徴として、組み込みDBとしての使い方を紹介。

 組み込みDBという言葉は、「組み込み機器向けDB」「アプライアンス向けDB」「アプリケーション組み込みDB」の3つをそれぞれ指す。で、Firebirdはそれぞれに対応しているという話。クライアント/サーバー型と組み込みライブラリ型で同じコードから使えるし、どちらの場合もフリーで利用ができる(MySQLの組み込みライブラリ型はライセンスが発生)。MIPS版やARM版もあり、多くの組み込み機器向けDBMSが商用なのに対してフリー、と。ただし、Windows CEに移植できないかとよく尋ねられるが、named pipeを多用しているので難しいとの話。

 あと、評価ボードは値段が高いので個人が移植するケースは多くないとか、Windows CE+SQLiteは日本語コード処理が面倒とかいう話も面白かった。

MySQL日本語処理問題(日本MySQLユーザ会/MySQL株式会社 松信嘉範氏)

 前半では、MySQLのUTF-8サロゲート文字問題を解説。MySQL 5.1までは3バイト文字までしか使えないうえに、サロゲート文字が化けるのではなくその文字以降が消されてしまうという問題がある。

 で、MySQL 6.0ではサロゲート文字に対応したことを紹介。サロゲート文字に対応したUTF-8を「utf8」として、5.1のutfを「utf8mb3」という名前に変更した。5.1のテーブルを6.0にコピーすると、utf8はutf8mb3になる。

 という機能的な話を前半として、後半はDBチューニングの観点からUTF-8の問題点であるバイト数増の問題を解説した。たとえば、VARCHAR(100)は、MySQL6.0のutf8では400bytesになる。これはテーブルをできるだけ小さくするというデータベースチューニングの原則に反する、という話だった。で、チューニングの観点からはEUC-JPが現実的と思う、ただしEUC-JPはエンコードがばらばらなので(IE、Firefox、Javaなど)、アプリ層で変換が必要になる、という話だったような。

 そのほか、シフトJISや日本語EUCとの変換機能はMySQL内部では用意していなくてアプリ側のすべきことだと考えているが意見募集中とか、日本語文字列のソートはばらばらでJIS X 4061に準拠していないとか、MySQL 5.1から日本語テーブル名に対応した(けどまだ使わないほうが無難)とかいう話を紹介した。

SE-PostgreSQL(日本セキュアOSユーザ会 海外浩平氏)

 SELinuxのポリシー定義をPostgreSQLの行や列単位のアクセス制御に適用するSE-PostgreSQLの紹介。

 もともと、ファイルのパーミッションとDBのACLは似たようなものなのに、別々のアクセス制御の仕組みとなっていて一貫性がない。これを、SELinuxのポリシーに統一しようというのがコンセプト。

 行単位のアクセス制御では、タプルにタプルにsecurity_context属性を付加。アクセス制御のない行は、あたかも存在しないように見える。

 いっぽう、列レベルのアクセス制御では、create tableのときに、カラムにcontext=で指定。適用は、クエリを解析して、アクセス権のない列への参照があるとアボートするようになっている。これはwhereなどに指定されているカラムも含む。ただし、参照はできるがユーザーには返さないuse権限というのもあり、whereでの条件指定だけできるという制御もできる。ほか、伏字化して返す関数に権限昇格の権限を与える、などの機能もある。

 PostgreSQL 8.3.1のFeature Freezeを知らなくて出しそこねたので、8.4でのマージをめざす、というのがすごいと思った。

大学におけるデータベース教育(長岡技術科学大学 湯川高志氏)

 データベース教育の実際について、大学教育と社会のニーズとのジレンマをまじえて語っていた。工学関連の教育プログラムでは、JABEEという認定があって、生徒の達成度を、いわば企業のISO9000シリーズのように認定しているのだとか。

 大学としては、装置やソフトのハウツーだけ教える教育はやりたくない。そこで、SQL文の書き方を教えるのではなく、RDB設計論やリレーショナル代数を中心に教えている。物理的データ格納形式や、問い合わせの理論についても、トピック程度にとりあげている。

 一方、自習用には湯川氏が参加しているNiigataLinuxのCDを配布している。LinuxのインストールCDであると同時に、Windows用のApache/PostgreSQL/PHP環境のインストールもできて、XAMPPと似たコンセプトになっている。

 質疑応答では、企業の人から「データベース理論だけではなくて、データベースを含むシステムの構築についても学んでほしい」という意見が出て、いろいろやりたいが講義時間が限られるという大学側の事情が語られた。また、学生さん(たぶん)からは、技術力とコミュニケーション能力のどちらかが重要かという質問も出て、コミュニケーション能力は定量的なものではないので実習などのプロジェクトの中で学んでほしいという回答があった。

パネルディスカッション

 なんか本当に仕込みなしでパネルディスカッションをやったらしい。日本MySQLユーザ会の堤井氏をモデレータに、日本PostgreSQLユーザ会の片岡氏、日本MySQLユーザ会の松信氏、Firebird日本ユーザー会の木村氏が登壇。みなさん、話が面白く、けっこう突っ込んだ話も出ていたように思う。

  • 最近のコミュニティの動向
    • 片岡氏
      • PostgreSQL Conferenceと総会をやった
      • 年々人数が増える
      • 今年はEnterprise Trackが満杯で、Community Trackが人が少ないくらい(笑)
    • 松信氏
      • MySQL社でWeekly Seminorをやっている
      • MySQL Conferenceもやっている。無料(笑)
      • ユーザーサイドの濃い人がどんどん情報を発信している
    • 木村氏
      • ブラジルで大人気
      • 2~3世代のマシンや不安定な電源事情で、ほかに選択肢がない
  • エンタープライズへの浸透
    • 片岡氏
      • Ver.6までは機能追加だったが、Ver.7からは性能や安定性を中心にしている
      • Skypeのバックグラウンドや、ゆうちょのWebにPostgreSQLが採用されている
      • 開発コアメンバーの何人かがSunに就職し、Solarisでの最適化も進んでいる
    • 松信氏
      • ソニーでは2003年ごろ、コスト削減のためOracleからOSS DB(MySQL)へ移行の動き
        • ストアドプロシージャでガリガリ書いてるアプリを移植するのは現実的ではないので、新規開発
        • Oracle技術者のMySQL技術者へのスイッチ教育に力を入れた
    • 木村氏
      • 大規模事例はない
      • 快適に使えるのは、スレッドモデルで100コネクションぐらいまで、プロセスモデルで数百コネクションぐらいまで
      • ドイツ通信社の記事DBがFirebird 1.2
      • 小規模の利用に向いている(特定用途)
      • ボーダフォンで利用しているというので驚いたら、ボーダフォン・フィジーだった(笑)
      • ブラジルの銀行で採用? 大丈夫か?(笑)
  • ユーザー層の変化
    • 片岡氏
      • OSS DBは無料なので初心者の学習に便利
      • 敷居が低くなっている
        • 初心者の人も増えて、複数のバージョンが知らぬ間に入ってしまっている人の質問も見受けられるようになった
        • これをポジティブに考えて、初心者向けのセミナーを定期的にやりたいと話している
      • MLの様子では、6~7割がソースからビルドしている
    • 松信氏
      • MySQL95%はバイナリからインストールしていると思う
      • テーブルとはなにか、インデックスが必要な理由、データサイズを小さくする必要性、など、体系だった教育がほしい
      • いま日本語でのDB学習カリキュラムに関しては、くやしいけどOracle masterがおすすめ
        • これは変えたい
    • 堤井氏
      • データの扱い方や形式など、データ処理のセンスを、大学などで教えてくれるといい
      • DB術者は平均年齢が高い?
    • 木村氏
      • 従来はFirebirdをビルドするのにFirebirdがいる、という難しい状態だったので、ビルドして使っている人はほとんどいないと思う
      • 何となく使われはじめて、そのうちデータが大きくなってほころびが出る、というケースがある
        • 30GB以上のテーブルで壊れるバグがあった。ただ、そんな大きなテーブルというのもどうか
  • データ量
    • 片岡氏
      • 増えている
      • 7のころ、VACUUMが重くてDWHには無理と言われた
        • 1つのテーブルのVacumに1日、という事例も
      • 8で改善された
    • 松信氏
      • Facebookの事例
      • メモリだけで20~30TBのデータ
      • でもインデックス作成のときのロック時間を短くするために1つのテーブルは小さく
      • いかにオペレーションを楽にできるかが重要
    • 木村氏
      • ネットワーク監視のDBの事例
      • 30万レコード/日
      • 1日1テーブルにした
      • 1か月でエクスパイヤ
      • VACUUMいらない
      • ログローテーションと同じ手法
      • インデックスは? それいらない(笑)
    • 片岡氏
      • PostgreSQLでは、テーブルの継承を使って分割すると、1つのテーブルのようにSELECTできる

ライトニングトーク:仮想化環境でのデータベースベンチマーク(日本仮想化技術 宮原徹氏)

 …といっても、これからやりたいという話。

 日本仮想化技術に、「仮想マシンでDBを動かしたい」という問い合わせが増えているのだとか。いままでより要求されるパフォーマンスや可用性の水準が高い。I/Oボトルネックはどれぐらい、とか、メモリのページングの影響は、とかいった疑問点がある。

 なので、ベンチマーク環境を作った。FCディスクアレイにSCSIディスク42台。すべてヤフオクで揃えた(笑)。あとは、やる人募集中、とのこと。

ライトニングトーク:階層構造化データベースG.T.M.のご紹介(沢田潔氏)

 RDBMSの前時代の技術の階層構造化データベースだけど、まだG.T.M.というDBMSが活躍しているという話。いわく、ハイパフォーマンスで、タイ2位の銀行や、欧米の小規模の電子カルテDBでの採用例もあるとか。

G.T.M.は、もともとDECにあったDBMSを参考に作ったもので、1998年にGPLで公開。VMSでも動く(ここで会場からなぜかどよめき)。2008年にFidelityグループの会社が買収した。Cachéに内部構造が似ている。「SQLを使うことがオーバーヘッド」という思想で、かわりにM言語というのを使っている。

 調べてみると、G.T.M.もCachéも、医療分野で強いようだ。

技術サイトの紹介(日本HP 赤井誠氏)

 日本HPがOSSに力を入れているという紹介。ゼンリンの事例は、公開されている事例としては、国内最大級のPostgreSQLの事例だろうと。

 で、「オープンソース技術情報」というコーナーで、技術ノウハウや手順書を公開したり、過去のセミナーで使ったコンテンツと動画を公開したりしている、という紹介だった。

CentOS 5.2リリース間近(平初氏)

 「北米のエンタープライズLinux」が5.2をリリースしたので、CentOSCentOSも5.2が出るよ、という話。話した時点でフリーズされミラーに配布されているということだったのだけど、これを書いている時点では正式リリースされていないようだ。あと、日本語ポータルも近日公開予定との話。

「クロサギ」19巻

 「虚偽告訴詐欺」「闇サイト詐欺」の2編を収録。わりと小ネタ。

 今回の手口のふりかえりは、ネタバレにつき「続きを読む」で。

続きを読む »

与えられた木から、子→親への対応を作る(写経編)

 「与えられた木から、子→親への対応を作る」で自分が書いたコードがイマイチだったので、素直にお手本を参考にします。

 出題者のShiroさんのサンプルから。

(use util.match)

(define (get-parent-alist tree)
  (define (rec p t s)
    (match-let1 (n . ts) t
      (acons n p (fold (cut rec n <> <>) s ts))))
  (fold (cute rec (car tree) <> <>) '() (cdr tree)))

 黙読より朗読ということなので、Perlで写経してみます。

#!/usr/bin/perl
use strict;
use warnings;
use YAML;
use List::Util qw( reduce );

sub rec {
    my ($p, $s, $t) = @_;

    my $n = $t->{name};
    my $ts = $t->{node};

    my $r = reduce { rec($n, $a, $b) } $s, @{$ts};
    $p ? [{ child => $n, parent => $p }, @{$r}] : $r;
}

sub get_parent_alist {
    my ($tree) = @_;

    reduce { rec(undef, $a, $b) } [], @{$tree};
}

my $tree = Load(do { local $/; <DATA> });
my $result = get_parent_alist($tree);
print Dump($result);

__DATA__
- name: Root
  node:
    - name: Spine
      node:
        - name: Neck
          node:
            - name: Head
              node:
        - name: RClavicle
          node:
            - name: RUpperArm
              node:
                - name: RLowerArm
                  node:
                    - name: RHand
                      node:
        - name: LClavicle
          node:
            - name: LUpperArm
              node:
                - name: LLowerArm
                  node:
                    - name: LHand
                      node:
    - name: RHip
      node:
        - name: RUpperLeg
          node:
            - name: RLowerLeg
              node: 
                - name: RFoot
                  node:
    - name: LHip
      node:
        - name: LUpperLeg
          node:
            - name: LLowerLeg
              node:
                - name: LFoot
                  node:

 実行結果。

---
- child: LHip
  parent: Root
- child: LUpperLeg
  parent: LHip
- child: LLowerLeg
  parent: LUpperLeg
- child: LFoot
  parent: LLowerLeg
- child: RHip
  parent: Root
- child: RUpperLeg
  parent: RHip
- child: RLowerLeg
  parent: RUpperLeg
- child: RFoot
  parent: RLowerLeg
- child: Spine
  parent: Root
- child: LClavicle
  parent: Spine
- child: LUpperArm
  parent: LClavicle
- child: LLowerArm
  parent: LUpperArm
- child: LHand
  parent: LLowerArm
- child: RClavicle
  parent: Spine
- child: RUpperArm
  parent: RClavicle
- child: RLowerArm
  parent: RUpperArm
- child: RHand
  parent: RLowerArm
- child: Neck
  parent: Spine
- child: Head
  parent: Neck

与えられた木から、子→親への対応を作る

 Perlでやってみました。30分以上かかったと思うし、テラappend。効率からするとpushしていくほうがいいと思います。

 作ってからWikiの解答例を見たら、みなさんエレガントに書いてました ><

#!/usr/bin/perl
use strict;
use warnings;
use YAML;

sub ko_oya {
    my ($nodes, @parents) = @_;

    if (defined $nodes) {
	map { ko_oya_one($_, @parents) } @{$nodes};
    } else {
	return ();
    }
}

sub ko_oya_one {
    my ($node, @parents) = @_;

    my $name = $node->{name};
    my $subnode = $node->{node};

    my @children = ko_oya($subnode, ($name, @parents));
    my @mine = map { { child => $name, parent => $_ } } @parents;

    (@mine, @children);
}

my $tree = Load(do { local $/; <DATA> });
my @result = ko_oya($tree, ());
print Dump(\@result);

__DATA__
- name: Root
  node:
    - name: Spine
      node:
        - name: Neck
          node:
            - name: Head
              node:
        - name: RClavicle
          node:
            - name: RUpperArm
              node:
                - name: RLowerArm
                  node:
                    - name: RHand
                      node:
        - name: LClavicle
          node:
            - name: LUpperArm
              node:
                - name: LLowerArm
                  node:
                    - name: LHand
                      node:
    - name: RHip
      node:
        - name: RUpperLeg
          node:
            - name: RLowerLeg
              node: 
                - name: RFoot
                  node:
    - name: LHip
      node:
        - name: LUpperLeg
          node:
            - name: LLowerLeg
              node:
                - name: LFoot
                  node:

 結果。

---
- child: Spine
  parent: Root
- child: Neck
  parent: Spine
- child: Neck
  parent: Root
- child: Head
  parent: Neck
- child: Head
  parent: Spine
- child: Head
  parent: Root
- child: RClavicle
  parent: Spine
- child: RClavicle
  parent: Root
- child: RUpperArm
  parent: RClavicle
- child: RUpperArm
  parent: Spine
- child: RUpperArm
  parent: Root
- child: RLowerArm
  parent: RUpperArm
- child: RLowerArm
  parent: RClavicle
- child: RLowerArm
  parent: Spine
- child: RLowerArm
  parent: Root
- child: RHand
  parent: RLowerArm
- child: RHand
  parent: RUpperArm
- child: RHand
  parent: RClavicle
- child: RHand
  parent: Spine
- child: RHand
  parent: Root
- child: LClavicle
  parent: Spine
- child: LClavicle
  parent: Root
- child: LUpperArm
  parent: LClavicle
- child: LUpperArm
  parent: Spine
- child: LUpperArm
  parent: Root
- child: LLowerArm
  parent: LUpperArm
- child: LLowerArm
  parent: LClavicle
- child: LLowerArm
  parent: Spine
- child: LLowerArm
  parent: Root
- child: LHand
  parent: LLowerArm
- child: LHand
  parent: LUpperArm
- child: LHand
  parent: LClavicle
- child: LHand
  parent: Spine
- child: LHand
  parent: Root
- child: RHip
  parent: Root
- child: RUpperLeg
  parent: RHip
- child: RUpperLeg
  parent: Root
- child: RLowerLeg
  parent: RUpperLeg
- child: RLowerLeg
  parent: RHip
- child: RLowerLeg
  parent: Root
- child: RFoot
  parent: RLowerLeg
- child: RFoot
  parent: RUpperLeg
- child: RFoot
  parent: RHip
- child: RFoot
  parent: Root
- child: LHip
  parent: Root
- child: LUpperLeg
  parent: LHip
- child: LUpperLeg
  parent: Root
- child: LLowerLeg
  parent: LUpperLeg
- child: LLowerLeg
  parent: LHip
- child: LLowerLeg
  parent: Root
- child: LFoot
  parent: LLowerLeg
- child: LFoot
  parent: LUpperLeg
- child: LFoot
  parent: LHip
- child: LFoot
  parent: Root

追記2008-6-3

 回答例を見ていて気がついたけど、俺、問題の意味をとりちがえていたよ。しょぼーん。

「おもいでエマノン」



 カジシンの原作のよさは当然として、鶴田謙二がやはりすばらしい。

 で、年寄には甘すぎの話だよなぁとか斜に構えつつ読んでいたら、「同じことなのよ」で改めて正面突破された。かなわんなぁ。

義経伝説と日本人

義経伝説と日本人 (平凡社新書)
森村 宗冬
平凡社
売り上げランキング: 455594

 「民明書房の本が実在すると思って神保町を探し回った若い頃の経験をカミングアウトしている歴史解説書」というネタで「と学会年鑑AQUA」に紹介されていた本。

 それぐらい緻密に史料分析し、「判官びいき」→「義経生存説」→「義経蝦夷脱出説」→「義経大陸渡海説」→「義経清朝先祖説」→「義経=ジンギスカン説」という俗説の流れと由来を丹念に、かつ新書の枠で平易に解説していて面白い。いわく、義経伝説は架空の文献を根拠としたり、どうみても語呂あわせな由来を根拠としたりと、民明書房のようなエンターテイメントと見るのがよい、と。

 と同時に、「判官びいき」を、たんなる同情ではなく、成功者への妬みや、自己反省なき被害者意識といった、どす黒いネガティブな感情として描く。また、蝦夷脱出説が徳川幕府の蝦夷支配の正当化の道具になったことや、「義経=ジンギスカン説」がネガティブなルサンチマンからくる自己肥大意識と西欧コンプレックスに結びつき大陸支配論に発展したことも合わせ、そろそろ「判官びいき」はもう止めませんか? という話でまとめている。

 以下、メモ。

  • 判官びいきの起こり
    • 鎌倉前期の「平家物語」では、戦記を中心に、自滅していく武将としての姿
    • 室町時代の「義経記」では、戦記はさておき、生い立ちや没落の悲劇を中心に描かれる。ついでに容貌も美少年ということに
    • 近代の東北では、「忠臣蔵」などでも義経がワンシーン登場するという無茶振りも
    • 戦国時代の敗者意識から生まれ、江戸時代の身分安定で決定的に?
  • 下地
    • 「清悦物語」
      • 義経の家来が人魚の肉(?)を食って死なない体になる話
    • 残夢伝説
      • 江戸時代に義経の家来の常陸坊海尊が残夢という名の老僧として現れたとする伝説
    • 「御伽草子」
      • 義経が修行時代に一時、蝦夷に渡っていたとする伝説
  • 生存説、蝦夷脱出説
    • 寛文7(1667)年、幕府の巡検使一行、オキクルミ=判官説を松前藩官僚から聞く
      • どう見ても語呂合わせの冗談です
    • 林羅山、俗説として「蝦夷脱出説」を紹介
    • 寛政11(1799)年、近藤重蔵、義経神社を建てる
    • 元禄3(1690)年「残太平記」→元禄13(1700)年「本朝武家評林」と、平泉からの脱出方法がエスカレート
      • 身代わり説の定番の成立
    • 正徳2(1717)年「義経勲功記」
      • 残夢伝説+清悦物語で、義経や弁慶が不老不死の仙人となったという物語
      • 「シャクワン=判官」説(語呂合わせ)
  • 大陸渡海説
    • 元禄年間「可足記」
      • 義経が韃靼の金国に渡ったとする説
    • 享保2(1717)年「鎌倉実記」
      • 「金史」別本を根拠とする
        • 新井白石「どう見ても捏造です」
        • 金田一京介:「沢田源内による偽造」説
        • 岩崎克己:「著者の加藤謙斎による偽造」説
  • 清朝先祖説
    • 天明3(1783)年「国学忘貝」
      • 清王朝編纂の「古今図書集成」にある「図書輯勘録」で、清朝皇帝が「源義経の子孫である」と宣言している、と記述
        • 伊勢貞丈「そんな記述ありませんが」
        • 桂川中良「「古今図書集成」の目録を調べたけど「図書輯勘録」なんて存在しなかった」
    • 日本国として光栄である、というキナ臭い空気の発生
  • 義経=ジンギスカン説
    • シーボルト「日本」
      • 「カン」=「カミ」、説
      • 韃靼と蒙古を混同したこじつけ?
    • 明治12(1879)年「The Identity of the Great Conqueror Genghis Khan with the Japanese Hero Yoshitune」
      • 日本人の末松謙澄がイギリスで発表した英語論文
      • 「源義経」=「ゲンギケイ」=「ジンギスカン」、父の名のエゾガイは「蝦夷海」、といった語呂合わせ
      • 著者名を明かさず、イギリス人の著作に見せかけ「義経再興記」として翻訳
        • 国威高揚の目的
    • 大正13(1924)年「成吉思汗ハ源義経也」
      • 小谷部全一郎著
        • ロマンチスト、宗教家、理想家、ドグマの重い障壁(金田一京介)
        • 没落貴族である自己を投影?(大森金五郎)
      • 歴史学者による反論
        • 「成吉思汗は源義経にあらず」
        • が、岩崎克己「鰯の頭を信心している人に向かって、尻尾に含有されるヴィタミンの効用を説明しているようなもの」という反省も
      • 大川周明や甘粕正彦などナショナリストが絶賛

 | HOME | 

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly