名古屋Reject会議を開催しました


名古屋Ruby会議02のとなりで名古屋Reject会議というイベントを開催してきました。
Rubyという言葉を使ったら負け」みたいな雰囲気のある謎なイベントでした。たのしかった!

当日は[twitter:@maeda_]さんがustream中継を、[twitter:@wof_moriguchi]さんがタイムキーパーをやってくれて、ものすごく助かりました。主催者は笑いながら発表を聞いてただけです、ごめんなさい。

発表資料まとめ

漏れがあったら教えてください。

FAQ: なんでこんなことやったの?

[twitter:@Dominion525]「Ruby会議本編だけだとつまんないので、自重しない感じのイベントもやりたいですね」
[twitter:@mzp]「いいですねー」
[twitter:@Dominion525]「じゃあ、みずぴーさんとりまとめよろしくお願いします」
[twitter:@mzp]「 ( ゚д゚ ) 」

FAQ: なんでRejectなの?

Ruby会議に併設されるReject会議の名前をパクりました。
本会議よりも先に発表者が決まったりと、謎な現象も起きたりしました。

FAQ: なんで休憩時間がないの?

「どうせ、Reject会議をぶっとおしで聞く人もいないしいいよねー」という理由です。実際は、ぶっとおしで聞く人しか居ませんでしたけど。
発表時間のバッファが無いのがちょっと心配でしたが、特に遅れもなくできました。発表者のみなさん、ありがとうございます!

FAQ: なんで廊下なの?

同じ階の部屋がとれなかったんです..。

FAQ: なんであんなにカオスなの?

しらんがな。

開発者用Webチャットシステム『AsakusaSatellite』をリリースしました

最近、[twitter:@suer]、[twitter:@mallowlabs]、[twitter:@shimomura1004]と夜な夜なSkypeでチャットしながらソフトウェア開発をしてるんですが、だんだんとSkypeチャットの機能に対する不満が溜ってきました。
というわけで、SkypeチャットをリプレースすべくWebチャットシステムを作ってみました。
開発者にとってハッピーな機能満載なので、是非使ってみてください。 →公開サイト

Skypeの不満点

  • 全文検索ができないので、過去の発言を探すのが面倒
  • コードがハイライトされない
  • #42と書いてもRedmineのチケットにリンクしてくれない←

AsakusaSatelliteの特徴1: 普通につかえる


最近のChromeはけっこう凄くて

  • リアルタイムな発言更新
  • デスクトップ通知
  • D&Dによるファイルアップロード

が平気でできてしまいます。

いわゆる"チャットアプリ"に必要な機能は、ちゃんと実装されています。

AsakusaSatelliteの特徴2: 全文検索可能


バックエンドとしてhttp://groonga.rubyforge.org/を採用しているので、過去の発言の全文検索が可能です。
これで埋もれてしまった過去の発言も簡単に探すことができます。

AsakusaSatelliteの特徴3: チケットリンク


AsakusaSateliteは開発者向けなので、「#325」と発言すると該当するRedmineのチケットにリンクを貼ります。RedmineAPIキーを設定すれば、自動でチケット名も取得します。

これがあると「#325 おわったよー」みたいなやりとりが、すごく簡単になります。

AsakusaSatelliteの特徴4: チケットリンク


CodeRayによるシンタックスハイライトに対応しています。

AsakusaSatelliteの特徴5: iPhone UI

iPhone用のUIも用意されています。[twitter:@mallowlabs]さんが「iPhone 4しか持ってねーよwww。 3Gとか3GSのことなんて知らねーよwwww」と言いながら、必死でiPhone 3GSに対応させてました。

その他の特徴

[twitter:@mallowlabs]さんの発表スライドに書いてあります。

F#プログラマのためのMaybeモナド入門


http://twitpic.com/3w34bo

はじめに

モナドといえばHaskellHaskellといえばモナドが有名ですが、モナドは特定の言語とは無関係の仕組みですので、F#でも使えます。ただ単に使えるだけでなくコンピュテーション式というモナドをより便利に使うための文法まで用意されています。
この記事では、option型を便利に扱うためのMaybeモナドを例にモナドのすごさを紹介していきます。

Maybeモナドのすごいとこ

option型っていいですよね。ぬるぽので落ちる心配もないですし。Maybeモナドはそんなoption型を便利に扱うためのモナドです。

option型を扱うのにMaybeモナドと呼ばれてるのは、Haskell由来だからで特に重要な理由はありません。

DBからの値取得とかHttpリクエストからのパラメータ取得などの外部とやりとりする関数は必ず成功するとか限らないのでoption型を返す関数として実装するのが安全です。でもoption型を返す関数を繋げていくとネストが深く、読みづらくなってしまいます。

例えば、 dbというMapに格納されている"x"と"y"を加算する関数は次のようになります。

(* 値が格納されたMapを作る *)
let db = Map.ofList [("x", 1); ("y", 2); ("z", 3)]

(* dbに格納されている"x"と"y"を加算する関数 *)
let x_and_y =
    match Map.tryFind "x" db with
    | Some x ->
        match Map.tryFind "y" db with
        | Some y ->
            (* xとyが取得できたので加算して返す *)
            Some (x + y)
        | None ->
            (* yの取得に失敗したのでNoneを返す *)
            None
    | None ->
        (* xの取得に失敗したのでNoneを返す *)
        None

(*
  実行結果
  val it : int option = Some 3
 *)

ネストが深いくて読みづらいですね。この例は2つだからまだいいですが、3つや4つの値を扱うことを考えるとげんなりしてきます。

これをMaybeモナドを使って書き直すと次のようになります。

let x_and_y' =    maybe {
        let! x = Map.tryFind "x" db (* 失敗したら全体がNoneになる *)
        let! y = Map.tryFind "y" db (* 失敗したら全体がNoneになる *)
        return x + y (* xとyを加算して返す *)
    }

(*
  実行結果
  val it : int option = Some 3
 *)

ネストが浅くなってるしコードの量も減って読みやすくなっています。 しかもMap.tryFindのどちらかがNoneを返したらx_and_y'もNoneになるので、安全性も失われていません。

さあ、みんなもMaybeモナドを使いましょう!

Maybeモナドの裏側


http://www.flickr.com/photos/audra_b/3831200/

さて、なぜこんなことができるのかを見ていきましょう。

コンピュテーション式による変換

maybe { ... }はコンピュテーション式と呼ばれる構文で、コンパイル時に次のような変換が行なわれます。(一部抜粋)

{¦ let! pattern = expr in cexpr ¦} builder.Bind(expr, (fun pattern -> {¦ cexpr ¦}))
{¦ return expr ¦} builder.Return(expr)

おおまかに言うとlet!がbuilder.Bindに、returnがbuilder.Returnに変換されます。

この変換規則に従って、先程の式は次のように変換されます。

(*
先程の式:
 let x_and_y' =     maybe {
         let! x = Map.tryFind "x" db
         let! y = Map.tryFind "y" db
         return x + y
     }
*)

(* コンピュテーション式を展開した式 *)
let x_and_y' =
    (* let! x = Map.tryFind "x" db *)
    maybe.Bind(Map.tryFind "x" db, fun x ->
      (* let! y = Map.tryFind "y" db *)
      maybe.Bind(Map.tryFind "y" db, fun y ->
         (* return x + y *)
         maybe.Return(x+y)))
Maybeモナドの定義

ここでのmaybeはBindとReturnを実装したMaybeBuilderクラスのインスタンスです。MaybeBuilderクラスは次のように定義されています。

type MaybeBuilder() =
    member this.Bind(x, f) =
        match x with
        | Some y -> f y
        | None -> None

    member this.Return(x) =
        Some x

let maybe = new MaybeBuilder()

コンピュテーション式を展開した式のBindとReturnも展開すると、次のようになります。

(* コンピュテーション式を展開した式
 let x_and_y' =
     maybe.Bind(Map.tryFind "x" db, fun x ->
       maybe.Bind(Map.tryFind "y" db, fun y ->
          maybe.Return(x+y)))
 *)
let x_and_y' =
    (* maybe.Bind(Map.tryFind "x" db, fun x -> ...) *)
    match Map.tryFind "x" db with
    | Some x ->
        (* maybe.Bind(Map.tryFind "y" db, fun y -> ...) *)
        match Map.tryFind "y" db with
        | Some y ->
            (* maybe.Return(x+y) *)
            Some (x + y)
        | None ->
            None
    | None ->
        None

結局、モナドを使わない場合と同じ式になりました。

まとめ:なにがすごいか

Maybeモナドを使うことで、optionを扱うコードを短く書くことができました。

今回はoptionを扱うコードを短く書くMaybeモナドを紹介しただけですが、他にも状態付きの計算を行なうためのStateモナドや非決定計算を行なうためのListモナドなどがあります。詳しくはAll About Monadsなどを参照してください。

このようにDSLをF#の枠組みの中で作ることができる上に、優秀なHaskellianの方々が○○モナドを既に大量に生み出しているので、それを活用することができるのがモナドのすごいところです。

さあ、今日からモナドを使ってプログラミングしましょう!

補足:モナドって何よ?

普通にモナドを使ってプログラミングする上では問題になりませんが、モナドとなるにはモナド則を呼ばれる規則を厳密に満たす必要があります。

けっして、コンピュテーション式で使えるのがモナドだったり、ReturnとBindを実装したのがモナドではありません。

詳しくはモナドを作りたくなったら、調べるぐらいでいいと思います。

サーバを作りながら学ぶWebSocketプロトコル

WebSocketって何?

WebSocketは、Javascriptでサーバとリアルタイム双方向通信をする仕組みです。概要は第1回 WebSocket登場までの歴史:Jettyで始めるWebSocket超入門|gihyo.jp … 技術評論社によくまとまっています。

この記事ではWebSocketサーバを実装しながら、どういうプロトコルかを解説します。サンプルコードはWebSocket Draft 76でechoサーバーを作ってみた - いろいろな何かのものを参考にさせていただいています。ありがとうございます。

※WebSocketプロトコルは現在ドラフトの段階なので、そのうち仕様が変わる可能性があります。この記事は20111/23時点の情報です。

プロトコル概要

WebSocketで通信を行なうおおまかな流れは次のようになります。

  1. クライアントとサーバの間でハンドシェイクを行ない、接続を確立する。
  2. データを双方向でやりとりする。

これを順番に説明してきます。

クライアントとサーバの間でのハンドシェイク


クライアントが接続するたびに、サーバには次のようなリクエストが送信されます。

GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
Origin: http://example.com

^n:ds[4U

※ 赤字の部分はハンドシェイクに使われる情報なので、接続のたびに変化します。

このリクエストに対して、適切なレスポンスを返すことで接続が確立されます。

まず、Sec-WebSocket-Key1Sec-WebSocket-Key2は暗号化されているので復号する必要があります。復号は数字部分/スペースの個数で行なうので、例えば12998 5 Y3 1 .P00は1299853100/5=259970620です。

これをコードにすると次のようなります。

def decode(self, s):
  '''ハンドシェイク中のキーを解析する。'''
  # 数字の部分だけをとりだす
  n = filter(lambda c : c.isdigit(), s)
  # スペースだけをとりだす
  m = filter(lambda c : c == ' '   , s)
  # 数字部分 / スペースの個数
  return int(n) / len(m)

次に、復号したSec-WebSocket-Key1(32bits)、同じく復号した Sec-WebSocket-Key2(32bits) 、リクエストのボディ部(128bits) を順に並べてmd5を計算し、これをHTTPレスポンストの本体にして送り返すことでハンドシェイクを確立します。
これをコードにすると次のようになります。

part1 = self.decode(fields['sec-websocket-key1'])
part2 = self.decode(fields['sec-websocket-key2'])

# 値を32bitのビッグエンディアンのバイナリーにする
CHALLENGE = struct.pack('>I', part1)

# 値を32bitのビッグエンディアンのバイナリーにする
CHALLENGE += struct.pack('>I', part2)

CHALLENGE += key

# /chalenge/のMD5 fingerprintを/response/に入れる
RESPONSE = hashlib.md5(CHALLENGE).digest()

あとはWebSocketプロトコルにそったヘッダをつけて、クライアントに送り返します。

HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Location: ws://example.com/demo
Sec-WebSocket-Protocol: sample

8jKS'y:G*Co,Wxa-

以上のことを図にまとめると次のようになります。

データ送受信

接続を確立したら、データの送受信ができます。WebSocketではデータの送受信はフレームという単位で行います。

テキストフレームは先頭に\x00、末尾に\xFFがつきます。例えば、"hoge"を送りたい場合は、"\x00hoge\xFF"になります。制御用のフレームもあるけど、こっちはなくてもとりえず動作します。

逆にフレームからテキストを取り出す場合は先頭の\x00と末尾の\xFFを除去すればいいので、次のようなコードになります。

data = self.request.recv(1024)

xs = itertools.takewhile(lambda x : ord(x) != 0xFF, data[1:])
self.RAW_DATA = "".join(list(xs))

コード

以上のことをまとめると以下のようなコードになります。

https://gist.github.com/737068

実行例

参考元の記事と同様に実行できます。

要するに

  • ハンドシェイクはちょっとややこしいけど、データの送受信は簡単
  • ライブラリ使ったほうが楽だよ。

MacBookAirの/usrが消失した件

先日の1/17に/usrを消してしまいました。

正確には、カレントディレクトリにできたusrディレクトリを移動させようとして、うっかり/usrを移動させてしまいました。

/usr消失→状況確認(22:30ごろ)

frama-cをインストールしようとして、/usrを消してしまう。

Skypeで助けたを求めたところ、速攻でTwitterに晒される。くそが。

落ちついて現状を確認すると

  • /bin/mvや/bin/cpは存在しているが、起動するとセグメンテーションフォールトになる
  • echo *すればファイル一覧は見える
  • /usrの移動先をFinderで見てもディレクトリが見えない

ということがわかった。

さっそくSkypeで「Finderで隠しディレクトリ表示させるにはどうしたらいい?」と聞くと「defaultsを使えばできるよ。/usr/bin/defaultsにあるけど」と言われて絶望する。

リモートインストールを試す→失敗(1/17 23:00ごろ)

無理なものはあきらめて、再インストールすることに。そもそも、こういうときのためにgithubDropboxを活用してんだよ。

手元にDVDドライブがなかったので、普段使っているiMac G5からリモートインストールにトライ。が、DVDを読み込んでる雰囲気はあるものの、ブートせず呆然とする。

このあたりでSkypeで助けを求めた人たちは飽きて美人天気の話をしてたっぽい。くそが。

ふてくされて寝る(1/17 23:30ごろ)

翌日、DVDドライブを借りることにして、この日はあきらめてる。

PhoneとiPadを活用して、いろんな人にいちゃもんをつけて寝る。→ いちゃもん1いちゃもん2

翌日、DVDドライブを借りて帰宅→iMac故障(翌日 19:00ごろ)

DVDドライブを借りたついでに、東急ハンズで文房具を物色して帰宅。
さっそくiMacに挿入したままSnowLeopardのインストールディスクをとりだそうとしたら、iMacが起動しない。今朝まで元気だったやん!
集合知たるTwitterを活用したらことろ「マウスをクリックしながら起動せよ」とのこと。が、まったく効果がなかったので分解してみるものの、強制排出の方法がわからずあきらめる。

Leopardインストール開始→復活(翌日 20:00)

SnowLeopardのディスクを取り出すのを諦めて、Leopardのインストールを開始。
インストールが完了し、MacBookAir復活。これからがんばって環境を構築します。

後日談

iMacが壊れたのでMac mini注文しました。
あとMacBook Air 11インチ欲しい!

『実践F#』レビュー

実践 F# 関数型プログラミング入門

実践 F# 関数型プログラミング入門

いげ太さんに献本をいただきました。ありがとうございます!
感想としてはすごくいい本! 入門書としてはオラリリーのプログラミングF#よりもいい気がします。

いいとろこ その1) 日本語の扱いについて解説がある

"対話環境では使えないけど、ソースコード中に記述してある分には問題ない"など、日本語のあつかいに関する言及がちょいちょいあります。
こういうのは日本人の書いた本ならでは、って感じがします。

いいとろこ その2) 説明が丁寧

  • はしょられがちなカリー化の説明に、3ページも割いてある。
  • F#/OCamlで多用されるシャドウイングの説明がちゃんとされている。

など、説明がとても丁寧でいいと思います。

いいとろこ その3)スタイルに関する言及もある

文法の解説だけに留まらず、

  • 引数の順番をどのように決めるべきか
  • nullよりも'a optionを使うべきである

などスタイルについての言及もあります。

単に文法だけ覚えると『C#のコードをF#の文法に直しただけ』みたいになってしまうので、こういうスタイルの解説はとてもありがたいです。

残念なところ

  • コンピュテーション式が非同期ワークフローにしか使われていない。optionモナドとかリストモナドも便利なので、説明がほしかったです。