Hatena::ブログ(Diary)

I am Bad at Math

2011-03-08

Sapporo.jsでJavaScriptの成り立ちについてLTしてきました。

12:27 |


当初はNodeのことを5分で話すつもりでしたが、id:tricknotesの「時間はどのくらいあればいいですか?」という有難い申し出を受けて設定したのが20分。

さすがに手元の資料では足りないのでJavaScriptの歴史についても話してきました。

そちらについては資料すら作ってなかったのでホワイトボード使いつつ記憶を頼りに延々しゃべっていくという・・・さらに字が汚くて見えづらかったと思います。すみません。

で、帰ってきてからざざざっと資料を作りました。

まずはECMAのトコまで。

JSってサイドストーリーがとっても多い言語なので突っ込んで調べるといろいろ新しい発見があり、ネタに事欠かない言語でもあります。そういうのを調べて行くとかなりJavaScriptに親近感が湧くようになるのでみなさんも是非。

と、話がずれてきましたがLTの後半に話していたサーバサイドJavaScriptについてはまた別途。


追記: id:koyhoge さんからご指摘頂いたJim ClarkはMosaicに関わっていないというのはその通りですね。

スライドを修正しておきました :) ありがとうございます。

2011-01-11

TOEICの点数が上がらない英語勉強法

01:52 |

これは最近よく感じる疑問。普通にきれいな英文を書けているような人でもなぜみんな一様に「もっと英語勉強しなきゃ」って言うのだろうか。もう勉強する必要ないじゃん。

TOEICの勉強している人は今600点だから、700点取らないとと言う。で、700点取ってる人は800点取らないとという。最終的にみんな900点以上を目指す勢い。もちろん何かを勉強することに異論は全然ない。むしろ大賛成だよ。でも「英語学」を勉強している訳じゃなく、その目的は英語を実際に使うことではなかろうか?いや、プロの翻訳家目指していたり比喩や暗喩バリバリの難しい文章を理解できるようにっていうのなら話はまた別だけどね。

英語を学ぶっていうのはつまり、プロトコルを学ぶこと。エンジニア向けに言い換えると「英語を学ぶということはTCP/IPを学ぶようなこと」と言ってもいいかもしれない。そう考えてみると英語を勉強している人っていうのは伝送プロトコルそのものを学びたいのだろうか?自分が思うにそうじゃなくってその先から送り出されてくるコンテンツにアクセスしたいんだよね?

それなら実際にもっとガンガン英語を使ってコンテンツにアクセスしていこう。

漠然と使うっていうのもなんなので手始めに「使う」を4領域に分解してみる。「読む」「書く」「聞く」「話す」の4つ。

「読む」に関しては全然問題ない。インターネットの普及でこれでもかとばかりに読むものがある。エンジニアであれば技術資料なんて英語てんこ盛りなんだからどんどん興味のある分野のものを読んでいけばいい。わからない単語は何度も出てくるようなものは辞書で調べるとしても、一度も見たことのないようなものはそれがキーワードとなっていない限りすっ飛ばしたってかまわない。TIPSが一つあるとすれば「あ、これ見たことあるけどなんだっけ」という単語は辞書を引き直そう。それなりの頻度で使われていてこれからも目にするはずだから。

さて、残る3領域の「書く、聞く、話す」だ。

「書く」っていうのもそれほどレベルが高いわけじゃない。得意とする分野のことについてブログ書いたりもできる。日本の技術ブログ文化って世界的に見てもスゴいんだ。良記事を書くことでそこから生まれるコミュニケーションも期待できるので言語の垣根を越えて興味を持てるものを題材に書くこと。

残るのが「聞く、話す」。

「聞く」と「話す」を切り分けて「聞く」から始めるのもありだろう。でも「話す」シチュエーションには「聞く」ことも含まれるだろうからこの際効率を上げて一緒にしてみよう。

まずは英語が下手な自分と英語で会話してくれる誰かを探さなきゃいけないんだけど、これが超絶難しい。相手にとって片言でしか英語を話せない人と会話するメリットを考えてみれば自明だね。その辺のソリューションが英会話教室なんだろうけど、教室に行く時間を空けなきゃならないし、さらには高額だ。

英語を話せる友達さえ作れればいいんだけどなー。と誰もが思っているんじゃない?

なんだか小学校に入学したときと同じ難題がパワーアップして今再び!って感じだ。

今から考えれば学校ってシステムはすごいって思わないかい?友達作りに理想的な条件が設定されているんだ。同年代の人、もしくは学びたいことが一緒の人たちが一カ所に集まっているんだなんてそうそうないだろう?

そういうインフラを今、僕らはどこに求めればいいんだろうか。

一番手頃だと思われるのはやっぱりfacebook?

でもFBで知り合ったからってそれがリアル会話にまで発展するかというとそんなことは滅多にない。たいていはチャットで済むんだから。「オレ、お前とリアルに話したい」って言ったらむしろ相手は引きまくるだろう。

自分の考えた中で最良の選択肢はやっぱり日本語版の出ていない、海外のMMORPGかなと。

MMORPGにはさ、まず目的があって(ボス倒すとか)、その目的を達成するためにレベルを上げるなんていう行動もさることながらマルチプレイヤー同士で「協力」することで心理的な連帯感が生まれるよね。で、その連帯感から友情って生まれやすいのは理解できることと思う。MMORPGを選んだのには理由があって、ゲームがリアルタイムで進行するってところ。テキストチャットで悠長にやりとりしている時間がなくなるとボイスチャットが登場するからね。

ここで引いちゃう人もいるだろう。

まさかヘッドセット付けてゲーム?オタクっぽくない?みたいな。

アメリカってその広大な国土に人がばらけているせいで都市部以外は実は娯楽が少ない。だから映画やテレビの場面を題材にしたジョークが多いのかも、同じ映画やテレビ番組をホント何回も見てるから。ま、そういった背景があればMMORPGが根付きやすいのは想像できるんじゃないかな。結果として相当な数の人たちがMMORPGを楽しんでいる。もちろん、女性も含めてね。親子で遊んでいる人だって珍しくない。

話を元に戻すと、ゲーム中のボイスチャットには「聞く」「話す」のトレーニングとしても最強レベルの効果がある。例えば10人や20人の努力がさ、君が英語の指示を的確に理解できなかったために無為に終わるかもしれないんだ。そりゃもう聞いている側としては最高度の集中力で相手の話す声を、内容を聞き取ろうと努力するハメになる。中にはマイクレベルが高すぎて声が割れていたり、もしくはノイズまじりだったり、もともと声が小さかったり、同時に複数が喋ったり、やけに話の長いやつがいたりとコンディションが良くないのは日常茶飯事。そんな悪条件下だとしても何とか相手の意志をくみ取っていかなきゃならない。だから普通に会話するよりも何倍もの集中力で相手の声に集中するんだ。わからない単語が聞こえたらその単語の重要度、聞き返すべきかなどを瞬時に判断していく。

うまく聞き取れないうちは意味を取れなくて失敗しちゃいけないという責任感から、いろんなサイトを巡って「読む」ことで予習し「聞く」ことを補完することになるだろう。そんなことを続けているうちに君が地道に調べ上げた知識が仲間にとって価値のあるものになる、その段階までくると今度は知識を「書き出し」たり、「声で相手に伝え」たりといった方法でその価値を共有することになる。

そう、いよいよ「話す」時だ。

残念なことにやっぱり最初はうまくしゃべれるわけがない。だから、まず「話す内容」を「書き出す」ことで練習することになる。「書く」ことが前提となっている場面ではもう日本語よりも英語そのままで情報収集したほうが効率が良くなるので「読む」のも同時進行だ。で、ちょこっとした文章を書いては仲間に「これでわかる?」なんて聞いたり。さて、いざ内容が決まり実際に話し始めても「おい今のなんつった?」「一番いい英語で頼む」「$%&*G*Y$@{)F???」などとはじめはホント散々だ。でも何度も赤っ恥書きながら次第に言い回しを覚えて慣れていく。恥をかくっていうのは日本人が極度に恐れることなんだけれども、どんどん恥をかいて凝り固まった自分のくだらないプライドをまずは粉々にぶち壊す。そして学習の螺旋階段をダッシュで上っていこうよ。

そのうちに音声を使ってチャットするのが苦痛じゃなくなって仲間たちとゲームを楽しめるようになるだろう。励まし励まされ喜びを分かち合ったり、喧嘩したりできる仲間とのコミュニケーションの中で文化の違いを学んでいけるようにもなるだろう。例えばさ、アメリカではあんなに犠牲者が出ているのにも関わらずなぜ軍人になる人がたくさんいるんだろうね?家族は反対しないのかな?などとまぁ仲間たちと話をしながら「へぇー」と思うことはそれこそいくらでもあるんだ。

と、MMORPGを英語を使いまくる素敵な手段として紹介してみたわけだけど問題点ももちろんあるから注意だ。

  • ゲーム自体を楽しめないと飽きる
  • そんじょそこらの英語教材よりもよっぽど時間食う。
  • こっちの夜はあっちの朝だ!
  • ゲーム上で使われる語彙に汎用性はない
  • ゲーム自体にハマッて抜け出せなくなる可能性
  • ゲームスキルもある程度必要
  • 人間関係を築けるだけのソーシャルスキルが必要

・・・いろいろあるなぁw

それでもトライしてみる価値はあると思ってる。初期投資もさほど必要ない。

さて、そろそろまとめに入ろう。こういったことを書いてきたのには理由がある。

f:id:badatmath:20110112014707p:image

学習曲線っていうとだいたいこんなS字カーブを描いていて、TOEICの点数が上がれば上がるほど単位時間あたりのスコア上昇率が低くなっていってしまう。だからTOEIC900点取ったぜなんていう人って凄まじいまでの努力をしていてすごいなって素直に思うんだけど、同時にもったいないなとも思うんだ。

TOEICがこれほどちやほやされるのは英語が使える基準をほかにどうやって設定していいかわからないから。実務でどういった局面で英語を使っていたかを履歴書に載せられないからその代わりにTOEICの点数を書いているだけじゃないか?例えばさ、英語を使ってlinuxのカーネル開発メーリングリストを束ねていましたなんていう経験があろうものならTOEICの点数なんて霞みまくって書く意味すらない。もしそういった人が履歴書にTOEICの点数がないために足切りされましたなんていったらそれはもう採用側のEpic Fail。だからできることならこのTOEIC一辺倒な世界を打ち破るためにも何か英語で実務的なことをこなしましたっていう経験を積もう。アメリカ人やイギリス人を採用するときにはTOEIC何点ですかなんて間の抜けた質問はせず、実務の話をするだろう?何か光るものを磨こう。ユニークな存在になろう。不安を点数で紛らわすな。「日本人だから英語下手だけど」っていうエクスキューズだけはナシ!そう最初に言っとくことで甘く見てもらおうだなんてそんな言い訳はナシだ!ビシッとさ、どこが悪いか指摘してもらえないと改善は望めない。

と、ちょう上から目線で書いてしまってごめんね!

まだMMORPGやってるのかって?実はもうやってないんだ。仲間たちとゲーム以外の手段で緊密に連絡を取れるようになったらもういいかなと思ってね。

あと参考までに書いておくと自分のTOEICの点数は700点(そんな点数で大丈夫かとか言うなーw)。5, 6年前に受けたっきりなんだけど会社から受けさせられない限り、自分からはもう受けないつもり。ただその代わりに英語を使って何かを始めようって思ってる。

最後に、こんなヒクツなタイトル付けてごめん!でもTOEIC捨てちゃえば点数もあがらないよ!

2011-01-01

Yet Another 白熱授業

00:12 |

みなさま、明けましておめでとうございます!

blog の更新が滞ってしまっていて大変申し訳ないのですが、今はちょうど node.js の本を執筆しているところでなかなか node ネタを書けないというかここでネタ書くヒマがあったら本を書けという心の縛りがありまして・・・。


でも新年明けましてということで今日は書いちゃうのだ。

さて、もう半年以上 CS のカリキュラム紹介をしていなかったんだけど、今日は Harvard 大学の CS50 という授業を紹介。折しも元日ということで学びに関連する記事をあげるのにはいい日だと思って。というか今日明日の夜はサンデル教授の白熱教室、再放送もやってることだし!

さて、CS50 はいわゆる CS の入門コース。

どこが白熱なのかというと、まず、やっぱり先生がイイんだよね。彼の名は David J. Malan。彼は Harvard での BA -> CS 専攻型の経歴を持ってて 1996 年にはかの Brian Kernighan に CS50 を教わっている(なんという贅沢!)。で、なおかつイケメン(って言ってもいいよね?)。彼の持ち味はまずはそのマシンガントークだ。勢いに乗ってガンガン飛ばして聴衆を圧倒しちゃうから聞いているほうは退屈って言葉を思いつく暇さえないくらいだ。このCS50 で扱われているのは初級のアルゴリズムとC言語。ま、どこの大学でもあるようなカリキュラムの一つだよね。

さて、ではほかの学校で行われる授業とどこが違うのだろうか?

例えば Youtube。この授業の中で彼はよく Youtube の動画を紹介するんだけど、これがもうね、うまいこと見つけてくるんだよね!例えばソートの授業での1コマでは Google の面接をオバマ大統領(このときは上院議員だったのかな)が受ける動画が紹介されていて、その中で Googleの中の人が「100万ある 32bit int をソートするのにもっとも効率のいい方法は?」なんて門外漢のオバマ氏にビシッと聞いちゃってる動画。

それにどう答えるかは

http://www.youtube.com/watch?v=HAY4TKIvSZE

こちらを参照のこと。

ほかにも電話帳を二つに引き裂く動画(バイナリサーチの授業、これはジョークだけど)や

http://www.youtube.com/watch?v=P4fcOLN9heU

ポインタの解説ではスタンフォードの学生(?)が作ったと思しきクレイアニメも紹介しちゃう。

http://cslibrary.stanford.edu/104/

こんな突飛な動画を見つけてきて紹介しては学生の関心をぐっと惹き付けながら授業を進めていくんだ。教科書をただ読んでいてもやっぱりつまらないからさ、Youtube にアップされた動画を使ってサブジェクトを常に身近なものとして捉えてもらい、集中力のレベルを引き上げ、そして記憶として授業の時間内に固定させる効果もあるんじゃないかと思う。僕は心理学者でもなんでもないからこんなことを言うのは憚られるんだけれども。

セメスターが終わりに近づくと最終提出プロジェクトの仕上げをするのにオールナイトHackasonも行われる。豪華なことにその日はピザや中華料理が振る舞われる上、朝まで残った人には朝食付きだ!こんなことが授業の一環として企画されちゃうなんてすごいよね。

そんなこんなでプロジェクトを仕上げた後にはお祭り(CS50 Fair)だ。家族や友達も連れておいでよってさ!

http://photos.cs50.net/Events/CS50-Fair-2010/

さらに CS50 のサイトには通販サイトまであって、そこではなんと「CS50グッズ」が販売されているんだ。CS50のロゴが入ったTシャツやスウェットのほかにクマのぬいぐるみまで!w 日本だと「計算機科学1」とかっていうロゴの入ったTシャツが売られちゃう感じ?

ということで、Harvard の CS 入門のちょっと変わっていたり楽しそうなことを列挙してみたけど、その中身は濃く、プログラムを組んだことのない人が1セメスターが終わってできるようになっていることはかなりハイレベルなんじゃないかな。(僕はCSの授業を受けたことがないのでこの程度はフツーだったらごめんなさい、でももし僕が全くプログラミングを知らない状態から12週でこのレベルをこなせるようになってるって考えたらすごいと思うんだ。はや7週目で Valgrind 触るとか!)

授業で扱われているスライド等々はすべてWeb上からダウンロード可能な上、授業のビデオ自体も全部見れちゃうので、文系卒できちんとした CS の授業を取ったことのないプログラマや中高生には是非オススメしたい教材。しかも2010年度のビデオからは transcript が完備されているので英語のリスニングは苦手だけどリーディングならという人でも全然大丈夫だからね。そのうち transcript 読むのがかったるくなってリスニング力があがるなんていうプログラマ的怠惰による英語力の進化も期待できたりして。

すべては

http://www.cs50.net

もしくは

http://www.cs50.tv

を参照のこと。

と、紹介はここまで。ここからはその授業の成り立ちの話ね。

さて、以前は Sever Hallの 200 人弱しか入れなかった教室で細々とやっていたこの授業はその人気の上昇に伴い 2008 年度からは Sanders Theatre という 1166 名まで入れる教室(というかコンサートでも使われるようなホール)で行われるようになった。件のサンデル教授の授業もこの Sanders Theatre だね。この通り、CS50 は昔から大人気な授業じゃなくって、2002 年には授業を取っている生徒数がわずか 100 人(!)を切る程度にまで落ち込んでしまっていたんだ。でもそれを David J. Malan は見事なまでに立て直した。この辺の経緯については彼自身が「Reinventing CS50」というタイトルで論文にしているので授業改革に携わる教員の方には是非参照してほしい。

http://www.cs.harvard.edu/malan/publications/fp310-malan.pdf

ん、いやむしろすべての人に参照してほしいところ。なぜならこの資料の中に綴られていることは教育界のみならず多くの領域に通じるはずだからね。

せっかくなのでこの論文を独りよがりにちょっぴり説明してみよう。この授業の再開発の主眼は

「学生をふるいにかけるのではなく、CSという分野に目を開かせる」こと。

そのために様々な努力が行われるんだけど、教える側ができるのは学生たちを後押しすることだけ。うん、そっちの側からできることってそれだけなんだよ!授業以外に平均すると15時間の workload が必要で、それだけでもキッツい授業なんだけど、それを教える側が惜しみないリソースを提供することで後押しするんだ。教材を全部自宅から参照可能にしたり、知ってて当たり前の、「ググれカス」とか言われかねないちょっと聞きにくいことなんかもあらためて質問できるように匿名で質問できる掲示板を用意したりね。

そう、学生にとっての親しみやすさを第一に考えるんだ。決してこれはカリキュラム内容を今までより易しくするとかそういうのじゃなくって、例えばコンピューターサイエンスのみならずギークカルチャーや internet meme を紹介したりという演出をしてみたり、Youtube の動画を紹介するのもこの怒濤の90分を学生に乗り切らせるためのちょっとした息抜き用にとして使ったりとかね。

このCS50の授業はほかの授業と比べたらそりゃもう最大の負荷を強いるんだけど、こういった取り組みの結果として Harvard では5番目(今年はもうちょっと上に行ってるかも)にデカい授業になることができたんだ。

と、こんな感じのことが書かれている。むしろこれは資料というより David J. Malan の冒険譚って印象だね。

最後に数字をあげておこう。2010度の CS50 の enrollment は前年比 56% 増の 525人になった。この 56% という数字がどれほどすごいかわかる?就職したらわかると思うけど、たいてい企業内での数字っていうと20%以内、つまり両手両足の指の数の和以上の数字っていうのはほとんど出てこないんだよ?しかもそれをダブルスコア以上だ!!

http://www.thecrimson.com/article/2010/9/13/students-class-cs50-more/

(もちろん facebook の創立者たる Mark Zuckerberg の影響もあるんだろうけどね!)

こんな、愛さえ感じられる授業、一度は受けてみたいな。

2010-11-01

node.jsとは何か(4)

05:44 |

さて、前回まで基礎部分をいろいろと説明したので今回からは実装について。現在のソースやその成り立ちを説明するのもいいんだろうけど、今日からはちょっぴりハンズオン形式に趣向を変えてみよう。ってことで


node.js を作っていくよ!



実装編その一はJSエンジンであるV8にJavaScriptのソースを食わせて実行する、つまりはオレオレJS環境を作るまでを扱うのだ。

V8はもともと他のソフトウェアに組み込まれて使用されることを想定(例えばChromeとかね)されているのでこういう作業が必要になる。


手順は大きくわけて二つ

1. まずはV8のソースを落としてきてV8のビルド

2. V8のソースディレクトリに自作のC++のソースを作ってコンパイル&実行

C++が出てきた時点で引いちゃったかもしれないけど、C++を使えるようになるのが今回の目的ではないのでまずはリラックス。C++っていったってそんなに難しく構える必要ないから!

例えば

int main(int argc, char* argv[]) {
  return 0;
}

っていうコード。

  • C++で実行プログラムを作るのにはmain関数が必要。
  • 関数には戻り値の型と引数の型を指定する。
  • 戻り値は指定されているとおりint型で返す。

ってことを実装しただけだ。いやそれC言語でしょって思うかもしれないけど気分は++。ちゃんとコンパイルすれば動くからね。簡単でしょ?もちろん Hello World さえ表示しないけどそれはそれで置いておこう。

あと、おそらくmain関数の引数が気になる、もしくはトラウマ的に嫌なイメージを抱く人もいるんだろうけど、引数の数と引数の値を渡されるんだというくらいの認識にとどめておいてぜーんぜん構わない。

もちろん興味を持ってC++をやろうって思った人はこんなでたらめな説明で満足せずにどんどん突っ込んで勉強していってほしい。


じゃあまずV8のビルドから。手順は

http://code.google.com/intl/ja/apis/v8/build.html

に載っている。

$ svn checkout http://v8.googlecode.com/svn/trunk/ v8

としてソースをsubversionのリポジトリから引っ張り出して、そのディレクトリで

$ scons

とするだけ、ここで注意したいのがsconsでビルドする際にx86_64環境の人は

$ scons arch=x64

としてCPUアーキテクチャを指定する必要があるってところかな。

さて、これをもとに本日のお題となるのがこちらのページ

http://code.google.com/intl/ja/apis/v8/get_started.html

V8の「さあ始めよう」だね。

このページを見てみると中ほどに Hello World 出力プログラムのコードが載っている。

まずはこのプログラムを実際に動かしてみよう。

このソースをコピペし、コンパイルして実行する。つまり

#include <v8.h>

using namespace v8;

int main(int argc, char* argv[]) {

  // Create a stack-allocated handle scope.
  HandleScope handle_scope;

  // Create a new context.
  Persistent<Context> context = Context::New();
  
  // Enter the created context for compiling and
  // running the hello world script. 
  Context::Scope context_scope(context);

  // Create a string containing the JavaScript source code.
  Handle<String> source = String::New("'Hello' + ', World!'");

  // Compile the source code.
  Handle<Script> script = Script::Compile(source);
  
  // Run the script to get the result.
  Handle<Value> result = script->Run();
  
  // Dispose the persistent context.
  context.Dispose();

  // Convert the result to an ASCII string and print it.
  String::AsciiValue ascii(result);
  printf("%s\n", *ascii);
  return 0;
}

これをさっきビルドしたV8のディレクトリにhello_world.cppとして保存し、次に

g++ -Iinclude hello_world.cpp -o hello_world libv8.a -lpthread

としてコンパイルしたら

$ ./hello_world

で実行だ。

成功すると Hello, World! とプロンプトに表示される。

おめでとう!


と、ここで終わらせるのはあんまりだ。なので解説を試みるね。


main関数が始まってすぐの

HandleScope handle_scope;

という行はHandleScope型のhandle_scopeっていう変数を作り出しているだけ。

これがないと下の方でHandle<...>と始まる行があるんだけど、そこでコケちゃう。イメージとしてはHandle型の変数達が棲息する場所を作るっていう感じかな。V8ではこの行はおまじないとしてほぼ確実に使うので気にしないったら気にしない。位置的にはHandle型の変数が現れる前に書いておけばオッケーだ。

Persistent<Context> context = Context::New();

この行では実行コンテキストを作っている。必ず一つはないとどこ実行していいのかわからないので落ちちゃうんだ。

Context::Scope context_scope(context);

作られたコンテキストに対し、この行で実際に実行コンテキストを設定する。で、その後に下の方で

context.Dispose();

として破棄しているね。

ちなみにこのコンテキストはいくつも作ることができて、Context::Scopeで設定することでそれぞれ実行可能。ブラウザの中でiframeの中に書いたjsをメインの画面のjsと一緒に実行するときなんかはこの仕組みを使って複数のコンテキストが切り替わっているってわけ。

コンテキストとはそもそも何かというと、例えば2つのプロセス、AとBっていうのがあってそれをマルチタスク環境上で同時に実行しているとしよう。1CPUだとこの2つのプロセスのうちどちらか一方しか瞬間的には処理できなくって、これをOSの中にあるタスクスケジューラってヤツがあたかもこの2つのプロセスを同時に実行しているように見せかけるためA->B->A->Bみたいに高速にスイッチングしているんだ。で、このうちCPUが現在こなしている処理っていうのをコンテキストと呼んでいる。

で、次の

Handle<String> source = String::New("'Hello' + ', World!'");

では"'Hello' + ', World!'"って文字列をV8用のJSソースとして設定している。

Handle<Script> script = Script::Compile(source);

ここがV8の結構特徴的なところだと思うんだけど、V8では読み込んだソースを初回実行時にコンパイルするんだ。バイトコードみたいな中間コードじゃなくってきちんとマシン語にまでね。ここで内部的に使われているアセンブラはSun謹製のアセンブラをさらにGoogleでチューンしたもの。

そうしてコンパイルしたものを

Handle<Value> result = script->Run();

で実行して今度はresultの中に結果を格納している。

後はその結果を文字列にしてプリント。

String::AsciiValue ascii(result);
printf("%s\n", *ascii);

どうだろうか、C++の知識よりもV8を使うためのお約束ばかりだ。

このようにものすんごく簡単にオレオレJSを作れちゃう。


さあ、このサンプルをもとにもうちょっとだけ踏み込んでみようか。次はJavaScriptファイル名を指定して、このプログラムに実行させたい。

先ほどのプログラムに対して加える変更内容は

1. 引数として指定されたファイルを読み込む

2. 先ほどの Handle<String> source に読み込んだ内容を食わせる。

と、こんだけ。


でだ。こっからはなるべく楽をしたい。なのでサンプルからパクれるものを探すのだ。V8のディレクトリの

sample/shell.cc

をみたらちょうどいい感じに見つかった。持ってきたのはファイルを読み込むその名もReadFile関数。

#include <v8.h>

using namespace v8;


v8::Handle<v8::String> ReadFile(const char* name) {
  FILE* file = fopen(name, "rb");
  if (file == NULL) return v8::Handle<v8::String>();

  fseek(file, 0, SEEK_END);
  int size = ftell(file);
  rewind(file);

  char* chars = new char[size + 1];
  chars[size] = '\0';
  for (int i = 0; i < size;) {
    int read = fread(&chars[i], 1, size - i, file);
    i += read;
  }
  fclose(file);
  v8::Handle<v8::String> result = v8::String::New(chars, size);
  delete[] chars;
  return result;
}


int main(int argc, char* argv[]) {

  Persistent<Context> context = Context::New();
  Context::Scope context_scope(context);

  // 引数が渡されなかったらエラーで終了
  if(argc < 2)  {
    fprintf(stderr, "script was not specified.\n");
    return 1;
  }
  HandleScope hs;
  // 引数に指定されたファイルを読み込む
  Handle<String> source = ReadFile(argv[1]);

  Handle<Script> script = Script::Compile(source);
  Handle<Value> result = script->Run();

  String::AsciiValue ascii(result);
  printf("%s\n", *ascii);

  context.Dispose();
  return 0;
}

これをolele.cppという名前で保存して、

g++ -Iinclude oleole.cpp -o oleole libv8.a -lpthread

としてコンパイルして実行してみる。

$ ./oleole

するとまずは

script was not specified.

と冷たくあしらわれて終了する。じゃ次に何か適当なJSのファイルをコイツに食わせてみよう。

var i = 1;
var j = 2;
i + j;

という内容のファイルをsample.jsとして保存し、今度は

$ ./oleole sample.js

として実行だ。

「3」という結果が返ってきて無事JSファイルをV8で実行することができただろうか。

エラー処理してないからちょっとしたミスでプログラムが落ちちゃうのはご愛嬌。

ということで実装編第一回のオレオレJS作成編は終了なのだ。

次回はlibevを使ったイベントループ実装編の予定。



ここからは補足説明。さっきのソースの中のReadFile関数で「v8::」っていうのがそこらじゅうに書かれているけどそれ取っちゃっても動くからね。

using namespace v8;

っていう行がそれ取っちゃっても動くようにするおまじないだ。

あとargcとargvっていうのはそれぞれコマンドラインからの引数の数と内容を含む。分かり辛いから例を挙げてみよう。

$ ./oleole sample.js

こうやって実行すると./oleoleとsample.jsの二つがmain関数に渡されるのでargcは2になり、argv[0]に./oleole、argv[1]にはsample.jsが入るって寸法。

ちなみにargcはargument count、argvはargument vectorの略だ。

UNIX系のOSやWindowsではmain関数に渡されるのはargcとargvだけではなくさらにもう一つenvpというものがあり、環境変数を受け取ることができる。

int main ( int argc, char* argv[], char* envp[] )

さらにMacのOS Xでは4つ目の、その名もappleというのがある。

int main ( int argc, char* argv[], char* envp[], char* apple[] )

手元にMacがないので確認できないけどapple[0]にはパス情報が入っているハズ。

あ、ついでにもう一つ。mainの戻り値を「0」に設定しているけど「0」っていうのは正常終了を表す。それ以外はエラーってことね。

2010-10-26

node.jsとは何か(3)

01:07 |

今日はnode.jsで採用しているCommonJSの話である。

CommonJSの説明だけだとあっという間に終わってしまうのでJavaScriptの歴史を混ぜ込んだら期せずして長くなってしまった。

さて、1995年に発表されたJavaScriptは開発当初「Mocha」と呼ばれ、次に「LiveScript」となり(実際Netscape Navigatorの2.0のアルファ版ではではこの名前だった)、最後にようやくJavaScriptになる(Navigatorの2.0B3から)という変遷をたどった。このJavaScriptという名前っていうのはJavaというコンパイル言語を補完するスクリプト言語にしたいという考えがあったからという話もあるんだけど、そのころ開発元のNetscapeはSunとの業務提携を発表しており、ちょうどそのころJavaが世に出てNetscapeブラウザ上でクールなJavaアプレットが動くんだぜなんて発表されて世間が沸いていたもんだからマーケティング上、Javaの冠をかぶせてその人気にあやからせてもらおうとNetscape側が思っていたとしても全然おかしくない。むしろそちらのほうが自然に感じる。

で、1996年にMicrosoftもJavaScript互換の言語を作るんだけど商標問題を避けるため、JavaScriptという名前を自社製品で使うことができなかったので結局JScriptという「心中お察しください」的な名前を使うことになる。

その後Netscape社はJavaScriptの地位を確固たるものにしようとしてその後ECMAという機関に標準化を依頼し、仕様が決まるのは1997年の6月のこと。結果としてECMAScriptという名前で標準化されたんだ。この4カ月後の10月にはMicrosoft陣営はInternet Explorerの4.0にてこのECMA-262 1st editionに準拠したと宣言する。ま、名前はそのまま変わらずJScriptなんだけどね。ただ、その仕様をもとにブラウザ間でのスクリプト動作の互換性が向上することとなる。

このころ大変だったのはそれを使うユーザ側。なんせJava、JavaScript、JScriptなんてあるもんだから、そりゃまあ混乱するのは目に見えていた。

本屋に行けば Java と JavaScript の本がごっちゃになってるし、採用担当の面接官もJavaScriptができるっていうのを勝手にJavaできるって勘違いするし、ただでさえバグの多い実装がバグの多いブラウザに乗っかってるせいで、セキュリティ関連の問題がぶわっと噴出するしね。だからJavaScriptを動作しないように設定していた人も多いんじゃなかろうか。このような黎明期の混乱のおかげで不幸なことに「トンデモ言語」的なイメージがJavaScriptに定着してしまうことになるんだ。

この後、1999年にIE5でActiveXとしてまず実装され、その後Mozilla系ブラウザやサファリでも実装されたXMLHttpRequestの登場がJavaScriptの転機を担う。ま、このへんからは説明もいらないと思うんだけど、そのXMLHttpRequestを利用した技術が2005年にAjaxと名づけられ、Google Mapでその技術が採用されるや否や爆発的な人気を獲得する。その後も続々とこの技術を利用するライブラリやフレームワークが開発され、現在ではWebアプリケーションを作成する上で欠かすことのできない言語となっているってわけだ。


で、話をECMAScriptのところまで戻すよ。

いわゆるJavaScriptベースと言われる言語の結構な割合が ECMA-262 3rd Edition をもとにしている。ActionScriptもその一つだ。

仕様書は下のリンクからダウンロード可能だ。

http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

この仕様書を見れば分かる通り、仕様ではいわゆる文法的なものが規定されており、さらにはクラスベースじゃなくってプロトタイプベースのオブジェクト指向言語なんだよーってこと程度しか書かれていない。この規定範囲の小ささが後になってCommonJS設立の動機の一因となるんだけどひとまず置いておこう。

それとここで ActionScriptってクラスベースじゃんよーって思った人もいるかもしれないがASでクラス使えるようになったのは2.0からだ。ちなみにその辺のActionScriptのオブジェクト指向サポートの変遷については以下の資料が詳しい。

http://www.adobe.com/livedocs/flex/3_jp/html/help.html?content=04_OO_Programming_12.html


さあ今日ようやくここでnode.jsに関連する話になるんだけど、じゃあnode.jsで採用されているV8ってどうなのか?V8のサイトを覗いてみれば分かる通り ECMA-262 3rd Edition に基づいているよって記述がある。でもその上にGoogleのオープンソースJavaScriptエンジンって記述もある。

これを分かりやすく言いかえると

JavaScriptはECMAScriptの方言である。

とするならばJavaScriptの実装(ここで言うとV8)はECMAScriptに準拠する。

ってことだね。


で、CommonJSの話。

node.js 以前にもさまざまな Server Side JavaScript の実装があったのはご存じの通り。RhinoやSpiderMonkeyのようになかなかポータブルなものからAptana Jaxerのように巨大なヤツ(というか全部入りのフレームワークだもんな)、V8でもv8-cgiっていう、V8をウェブアプリ書くのに使えるようにって試みもあった。そんな中、とあるエンジニアが乱立するServer Side JavaScriptの独自進化を憂い、サーバーサイドのJSには何が共通して必要とされるのかを考え、2009年1月末に自分の意見をブログで公開して議論の場となるメーリングリストを設けた。

これがCommonJSの始まりである。

以下がそのブログ

http://www.blueskyonmars.com/2009/01/29/what-server-side-javascript-needs/

ちなみに著者であるKevin DangoorはPython製ウェブアプリケーションフレームワークのTurbogearsやPaver、JS界隈でいうとDojoやBespinなんかを開発してきたエンジニアで現在はJSの本丸(?)、Mozillaで働いているという経歴の持ち主だ。

で、CommonJSが解決しようとした問題領域は

  • モジュール機構がない。
  • 標準ライブラリがない。
  • ウェブサーバーやデータベースとの標準的なインターフェースがない。
  • パッケージのマネジメントシステムがない。

といったことなど。要するにブラウザ以外でJavaScriptを利用する際に問題となる領域の解決を目指しているんだよね。

で、CommonJSで策定済み、もしくは策定中の仕様の一覧は以下のページにまとめられている。

http://www.commonjs.org/specs/

このうち、node.js が準拠しているのは現在のところ Module 1.0とUnit Testing 1.0のみだ。

http://wiki.commonjs.org/wiki/Modules/1.0

http://wiki.commonjs.org/wiki/Unit_Testing/1.0

仕様を見てみれば分かる通り、その内容はごくわずか。

だからnode.jsはCommonJSに準拠して云々というくだりで何やら難しそうだなんて思う必要なんか全然ないからね。

内容の割に長くなってしまったけどnode.jsとCommonJSについての話はこれくらい。

次回はいよいよ実装の話に移っていくつもりである。