(KLab×はてな エンジニア応援ブログコンテストへの応募エントリーです。)

会社の本棚には僕の個人的な持ち物であるオライリーの本が多い。最近もC++を勉強するためにとこれまたオライリーの"C++実践プログラミング"を買った。会社でC++に詳しいShu MASUDAさんは不思議そうに、

「何でその本を買ったんですか?」

と聞いてきた。確かにC++ならば他に良書が多数あるし、オライリーの"入門C++プログラミング"は大きく期待外れだったし、オライリーの本の翻訳は品質もバラバラなので当然の疑問だ。

Perlがわからない

2002年の暮れ頃、深夜の会社で一人、Perlモジュールのソースをわけも分からず端から読んでいた。5日間の期限でキャンペーン応募フォームの作成を命じられたためだ。その頃の僕は専門学校での教科書レベルのCと前職で使ったVBやASPのWindows上のWebアプリ経験しか無く、PerlといってもPerl4時代の書き捨て掲示板CGIを多少改修できる程度の知識しかなかった。

しかし突然、以前その会社に在籍していた先輩から、先輩自身がPerlで自作した独自Webフレームワークでのアプリ開発を命じられた。今考えてみれば先輩は、

「どうせ出来ないだろうが1日あれば自分が作れるからいいか」

という程度の考えで指示をしたのだろう。1日費やしても進捗どころか1行も書く事が出来ない状況に僕は暗澹たる気持ちになった。

ラクダの絵の描かれた本を買う

しかし未熟とはいえ業務としてのプログラミング、つまり「何が分からないのかも分からない」という状況への耐性は出来ていたので、リリースまで家に帰らない覚悟を決め、Webで評判の高かった"ラクダの絵の描かれた本"を買って先輩独自のWebフレームワークのソースを端から読んでいく事にした。

プログラミングPerl〈VOLUME2〉

当時は概要もまったく掴めぬまま愚直に全てのファイルを読んでいたが、今考えてみれば下記のような物だったと思う。

  • Perlで書かれた独自のApacheハンドラ。(何という拡張子をマッピングしていたかは忘れたが独自の物)
  • 独自のテンプレートライブラリ。
  • File IOのレベルで独自の基本ライブラリ群。(たしか内部的にTime::HiResだけはCPANモジュールを利用していた)
  • 全てPerl5からのオブジェクト指向機能を使用している。
  • コメントやドキュメントは全く無い。

基本ライブラリ群のトップレベルのネームスペースである2文字のアルファベットが作者である先輩のイニシャルであることに気付いた事でさえ当時の僕にとっては大発見だった。結局ソースコードもラクダ本も一通り読み通したものの、1行も書けずにリリース日を迎えた。

どんなにこっぴどく怒られるのかと思っていたが、先輩は"期待はずれ"といったため息を吐くだけで特に何も言わなかった。社長は技術のことは分からないが、"komagataがどうやら連日徹夜で何かやっていたらしい"ということは伝わっていたため「とりあえず寝ろ」ということで近所のカプセルホテルに泊まれることになった。結局アプリは先輩の会社が作り上げてリリースされた。

不思議な体験

しかしその後、あることを切っ掛けに今まで意味不明な記号の羅列や呪文の様にしか見えなかったソースや本の文章が急激に理解できるようになった。パズルのピースがはまっていくように次々と頭の中の記憶の断片が意味の通る知識としてつながった。これはちょっとしたカタルシスだった。その切っ掛けとはいろんなことを省いていくと、とどのつまり下記の1行の理解である。

sub foo {
    my $self = shift;
}

非Perlプログラマーへの解説

  1. subはperlで関数(サブルーチン)を作るキーワード。
  2. myはローカル変数宣言のキーワード。
  3. shift関数は暗黙的に@を引数に取る。shift(@)
  4. @はその関数の引数が配列として入っている。perlのサブルーチンには明治的な引数宣言は無い。
  5. インスタンスメソッドの第1引数はオブジェクト自身になる。
  6. つまりオブジェクトへの参照を$selfに入れるというperlでインスタンスメソッドを書くときのイディオム。

これがわかると「あれも読める、これも読める、読めるぞー!」とばかりに貪るようにソースや本を読み漁った。ラクダ本以外にもPerlと付くオライリーの本は片っ端から読んだ。("バイオインフォマティクスのためのPerl入門"以外)

先輩独自モジュール群はほとんどCPANやPerl本体に付いてくるより優れたモジュールが存在することがわかった。先輩自身のエゴで独自に手作りしたコードに苦しめられたことに腹が立った。オライリーの各種書籍やPerl, CPANの公式ドキュメントにはそういった独自のやり方とは正反対の世界標準・公式のやり方のための情報が盛りだくさんだった。

そこから僕が全く付いていけなかった先輩より遥かにスゴいプログラマーがインターネットには沢山いることがわかり、そこからオープンソースやプログラミングにどっぷりハマっていくことになった。

何故オライリーの本を買うのか

つまりオライリーとは僕にとって"全然分からないものが分かるようになる魔法の本"なのである。

今はPerlを書くことはあまり無くなったが、今でも未知の技術を勉強し始めるのに自然とあの"リアルな動物の本"を手に取ってしまうのである。

プログラミングPerl〈VOLUME2〉

プログラミングPerl〈VOLUME2〉

posted with amazlet at 09.10.05

ラリー ウォール ジョン オーワント トム クリスチャンセン

オライリー・ジャパン

売り上げランキング: 137434

Amazon.co.jp で詳細を見る

プログラミング言語 Ruby
まつもと ゆきひろ David Flanagan
オライリージャパン
売り上げランキング: 65705

まだ読み途中ですが、知らなかった事が結構ありますな。

4.5.3 属性と配列要素への代入

[]=メソッドに複数の引数を渡せるとは知らなかった。

class Foo
def []=(x, y, z)
puts x + y + z
end
end
% irb -r foo.rb
>> foo = Foo.new
=> #<Foo:0x1a10b34>
>> foo[1,2] = 3
6
=> 3

6の出力は分かるとして返値が3なのは何でなんだろう?

2010年02月24日追記:

bar = foo[1,2] = 3

こういう時のためですね、多分。

E-mobileのH11TからiPhoneへのデータ移行メモ。

連絡先

携帯マスターNX3 for EMOBILEとH11T用の最新ドライバーを入れてCSVファイルで連絡先をエクスポート。(Mac上のVirtualBox上のWindowsXPでは端末からのデータ転送が上手く行かなかったのでWindowsXPを入れたx61を使いました。)

Gmailの連絡先をCSVファイルでエクスポートし、上記のCSVとマージしてGmailに再度インポート。Gmailの連絡先は複数の連絡先を一つの連絡先にマージ出来るので整理。

メール

H11Tで"メール > 送受信メール > メニュー > エクスポート > 全件 > 本体"とする。"設定 > 外部接続 > USB > 接続設定 > マスストレージモード"としてPCと接続するとリムーバブルディスクとして認識される。

D:¥PRIVATE¥EMOBILE¥LIBRARY¥OTHER_UNKNOWN

上記のフォルダにメールが.vmgファイルとして保存されているので適当なスクリプトかツールで.emlに拡張子を一括置換する。Outlook ExpressかWindows Live MailでGmailにimap接続して(後者だとgmail.comドメインのアドレスを入れるだけでサーバーアドレスその他が自動的にGmailの物になるので楽)、.emlファイルをドラッグするとインポートされる。(メールが多いととてつもなく時間がかかるので他の方法を探した方がいいかも)

SMS/MMSのアドレスを取得したら「メールアドレス変わりましたメール」を送って終わり。(GmailとExchange Serverを使って同期・プッシュ式で使えるが、PCドメインからのメールはフィルタされていることが多いので携帯向けに送信する時はSMS/MMSが良さそう)

$ sudo yum update
$ cd /tmp
$ wget https://packages.endpoint.com/endpoint-rpmsign.pub
$ sudo rpm --import endpoint-rpmsign.pub
$ sudo yum remove ruby*
$ wget https://packages.endpoint.com/rhel/5/os/i386/ruby-enterprise-1.8.6-5.ep.i386.rpm
$ sudo rpm -ivh ruby-enterprise-1.8.6-5.ep.i386.rpm
$ wget https://packages.endpoint.com/rhel/5/os/i386/ruby-enterprise-rubygems-1.3.2-5.ep.i386.rpm
$ sudo rpm -ivh ruby-enterprise-rubygems-1.3.2-5.ep.i386.rpm

参照:End Point Package Repository

R0010185.JPG

iPhone買いました。やったね!

調子が悪い時は部屋を掃除したり、いらない物を思い切って捨てたりします。そうすると頭の中も整理された気分になって気持ちが良い。ここ数年ブログを書いてますが、ほぼ自分自身の外部記憶と化しており、ブログが散らかってると自分の頭まで散らかってる錯覚に陥ります。そこでブログの大掃除をやってみました。

古い日記のサルベージ

2002年頃の日記が数ヶ月分眠っていたのでマージしました。(この時期はASP1.0?とMS SQL Server6.5?で日記が書かれてたらしいのがびっくり。もうまったく使い方分か>りません・・・。)

テキストのフォーマット

Web日記時代から数えて9年分のテキストがありますが、いろいろなソフト・ハードで書いてきたので本文のフォーマットがバラバラ。

  • 手書きのHTML
  • MTのフォーマット(RailsのHelperで言うところのsimple_format)
  • Textile

これらが混在していたのでエントリーの内部フォーマットはHTMLに統一しました。

URLの永続化

これは一つ前のリニューアルからですが、エントリーのURLは「0を除く自然数」と決めました。永続性と意味を考えて永続性を優先しました。

他のリソースの置き場所

画像や動画はFlickrやYouTubeといった極力外部の長持ちしそうなサービスに置くことにしました。

リンクのクリーニング

全テキストから/src="(.+?)"/と/href="(.+?)"/でリンクを抜き出して、リンク切れや無くなったリソースを洗い出しました。もう存在しないものは仕方ないですが、記述間違いや移行時のミスで起こったリンク切れを修正しました。(タグの中で改行が無いという前提で)

認証の単純化

認証は大好きなBASIC認証にしました。エントリーを書く人は僕しかいないので、Rails標準のBASIC認証機能で十分です。user.ymlにアカウントとパスワードを書いて下記のようにしました。

class ApplicationController < ActionController::Base
  def authenticate
    authenticate_or_request_with_http_basic do |username, password|
      user = YAML.load_file File.join(RAILS_ROOT, "config", "user.yml")
      username == user["username"] && password == user["password"]
    end
  end
end
class DocsController < ApplicationController
  before_filter :authenticate, :only => [:new, :edit, :create, :update, :destroy]
end

検索エンジンに認識してもらう

sitemap.xmlを作ることで内部リンクの少ないこのブログでも各個別エントリーをインデックスしてもらえるようにしました。

HTMLのインデントが綺麗

hamlを使ったのでHTMLのインデントが完璧に・・・(うっとり)

HTMLのインデント問題。このブログに関してはHTMLのインデントは(少し妥協して)hamlを使うことにしました。ところが別の問題が。それはインデントされたエントリー内でpreタグを使った場合、意図してないインデントが表示されてしまうことです。

show.html.haml:

.doc
  = @doc

こういうテンプレで、

<pre>あああ
いいい
ううう</pre>

こういうエントリーを書いた場合、

<div class="doc">
  <pre>あああ
  いいい
  ううう</pre>
</div>

こういうHTMLが出力されるのでpreの2行目以降に余計なインデントが表示されてしまいます。

そもそもコードにはcodeタグだけでpreを使わないという手もありますが、通常のWYSIWYGエディタでは2個続きの改行は段落としてpタグがふられて、コード中の空行を意識しないといけないという面倒なことに。かといって改行イコールbrタグというのも気持ちが悪い。

どうしたもんか・・・。

関連:HTMLのインデントを合わせたい - p0t

追記:

hamlのfilterを使えばいい気がしてきたぞ!?

追記2:

hamlでtext_areaを使う時のメモ - Hello, world! - s21g

こちらの情報で解決!htmlでcontentノードの空白が表示に影響があるのはpreとtextarea。共通の問題なんですなあ。

詳細よりもまず大枠をつかみたい、という事をわかってくれない先輩

会社に入って半年、研修を終えて3か月の新人です。配属先で私の教育係に割り当てられた先輩と、どうも相性が悪いみたいです。この先輩は私が質問すると、いきなり詳細な内容を説明してきます。私がわからないと言うと、「わからないのは詳細を説明してないせいだ」と思うのか、説明がどんどん深い方向に進んでしまいます。

これは参考になるなぁ。僕もとにかく教えるのが下手で、質問を受けても、

「このURLに詳しく書いてあるよ」
「この本の第三章がおすすめ!」
「xxxクラスのoooメソッドがおかしいんじゃないかなあ?」
「そっかこれ難しいなあ、僕が直しておくよ」
「なんだろうね〜?これ」

などといきなり詳細を説明するのはまだましで、説明放棄に近いことしか言えませんでした。

質問した方は、全貌が見えず不安になる。
質問された方は、全てを教えないといけないと思い込み、ごく一部の詳細を教えるか、なげっぱなす。(全てを詳細に教えるのは無理なので)

対策として、質問者は全てを詳細に知ることを欲してるわけじゃなく、全体像(概要)が知りたいのだと思うので、本の目次的な、仕事全部の目次を用意すればいいのではないかとおもって、下記を作り始めてみました。

Webプログラマーチュートリアル – p0t

第2章 基本的なデータ型

2.1 整数

# 3 ;;
- : int = 3
# 3 + 4 * 2 ;;
- : int = 11
# (3 + 4) * 2 ;;
- : int = 14
# 2 - 3 ;;
- : int = -1
# 7 / 2 ;;
- : int = 3
# 7 mod 2 ;;
- : int = 1
問題2.1 次の整数値をOCamlインタプリタを使って計算せよ。

(1) 7 – 3 × 4

# 7 - 3 * 4 ;;
- : int = -5

(2) 7 ÷ 2 × 2

# 7 / 2 * 2 ;;
- : int = 6

(3) 7 × 2 ÷ 2

# 7 * 2 / 2 ;;
- : int = 7

2.2 実数

# 2.718 ;;
- : float = 2.718
# (3.0 +. 5.0) *. 8.0 /. 3.0 ;;
- : float = 21.3333333333333321
# (3. +. 5.) *. 8. /. 3. ;;
- : float = 21.3333333333333321
# 1.41421356 ** 2.0 ;;
- : float = 1.99999999328787381
# 1.41421356 ** 2 ;;
Error: This expression has type int but an expression was expected of type
 float
# 1.41421356 ** 2.0 ;;
- : float = 1.99999999328787381

んんん、実数キモイ・・・。

問題2.2 次の実数値をOCamlインタプリタを使って計算せよ。

(1) 2・3.14・10

# 2. *. 3.14 *. 10. ;;
- : float = 62.8000000000000043

(2) 1.732

# 1.73 ** 2. ;;
- : float = 2.9929

(3) 7/2

(* 間違い *)
# 7 / 2 ;;
- : int = 3
(* 正解 *)
# 7. /. 2. ;;
- : float = 3.5
# infinity ;;
- : float = infinity
# infinity +. 3.0 ;;
- : float = infinity
# 2.0 /. infinity ;;
- : float = 0.
# neg_infinity ;;
- : float = neg_infinity
# 3.0 -. infinity ;;
- : float = neg_infinity

2.3 文字列

# "Yokohama" ;;
- : string = "Yokohama" 
# "横浜" ;;
- : string = "横�\156" 
# "横浜" ^ "駅" ;;
- : string = "横�\156�\133" 
# "新" ^ "横浜" ^ "駅" ;;
- : string = "�\150�横�\156�\133" 
# "" ;;
- : string = ""
問題2.3 次のそれぞれの文字列をOCamlインタプリタに入力せよ。次に、それらの文字列を結合してみよ。

(1) 「東京」、「特許」、「許可局」、「局長」

# "東京" ^ "特許" ^ "許可局" ^ "局長" ;;
- : string = "�\157�京�\137�許許�\143��\128�\128�\149�"

(2) 「関数」、「型」、「言語」

# "関数" ^ "型" ^ "言語" ;;
- : string = "�\150��\149��\158\139�\128�\158"

2.4 真偽値

# true ;;
- : bool = true
# false ;;
- : bool = false
# true && true ;;
- : bool = true
# true && false ;;
- : bool = false
# true || false ;;
- : bool = true
# false || false ;;
- : bool = false
# not true ;;
- : bool = false
# not false ;;
- : bool = true
# not (false || not false && not false) ;;
- : bool = false
# not (false || ((not false) && (not false))) ;;
- : bool = false
# 2 < 3 ;;
- : bool = true
# 2 < 3 && 2.0 > 3.0 ;;
- : bool = false
# 2 < 3 || 2.0 = 3.0 ;;
- : bool = true
# not (3 < 2) ;;
- : bool = true
# true > false ;;
- : bool = true
# false > true ;;
- : bool = false
# true > true ;;
- : bool = false
# 2 < 3.0 ;;
Error: This expression has type float but an expression was expected of type
 int
問題2.4 次の文章の真偽をOCamlインタプリタを使って確認せよ。

(1) 2は3より大きい。

# 2 > 3 ;;
- : bool = false

(2) 3.1415の2乗より10は小さくない。

# not (3.1415 ** 2.0 > 10.0) ;;
- : bool = true

(3) 8を3で割った余りは2である。

# 8 mod 3 = 2 ;;
- : bool = true

(4) 3 4 5 と4 × 3は等しい。

# (3 + 4 + 5) = (4 * 3) ;;
- : bool = true

lispみたいvimで選択範囲を評価するみたいなプラグインがほしい・・・。

% rake time:zones:all
(略)
* UTC +09:00 *
Osaka
Sapporo
Seoul
Tokyo
Yakutsk

* UTC +09:30 *
Adelaide
Darwin
(略)

config/environment.rb:

config.time_zone = 'Tokyo'