SublimeText2にCtagsインストール時の注意点

Sublime Text 2とCtagsの組み合わせがすごい。開発スピードUP[Mac版] | codechord

上記手順を元に進めていくとCtrl+T, Ctrl+Rで.ctagsファイルを作るときに以下のアラートが出てビルドができない。

 

error: [Errno 2] No such file or directory

 

どうやらSettings - Userでcommandを設定するときに以下のようにすれば良い。"-R -f .tags"はプラグイン側で付加してくれるみたいです。

 

// "command": "/usr/local/bin/ctags -R -f .tags",
"command" : "/usr/local/bin/ctags",

WebWorkerとWebMessagingの比較

WebWorkerのプロセス間通信とWebMessagingは使い方が似ていて混同するので違いをまとめました。WebMessagingについてはiframeとwindow.open()とで挙動が違う箇所があったので分けて比較しています。

API比較

引数は以下のように定義しているとします。

  • $iframe = document.createElement(“iframe”);
  • $worker = new Worker(“worker.js”);
  • e: addEventListener("message", func, false) におけるfuncの引数
  WebWorker WebMessaging
親がlisten $worker.addEventListener(“message”, func, false); window.addEventListener(“message”, func, false);
親からpostMessage $worker.postMessage(data); $iframe.contentWindow.postMessage(data, origin);
子がlisten self.addEventListener(“message”, func, false); window.addEventListener(“message”, func, false);
子からpostMessage self.postMessage(data); e.source.postMessage(data, origin);
(iframeの場合は以下同等) window.parent.postMessage(data, origin);

selfはWorker内でのルートオブジェクトです。

ベンチマーク

以下の処理におけるパフォーマンスを比較しました。

  • 軽い処理を10000回
  • 重い処理を1回

http://www.asanoboylab.net/workervsiframe/

手元のChromeで確認するとこのようになりました。

  Web Worker Web Messaging(iframe) Web Messaging(window)
10000 light tasks 1093msec 1553msec 1480msec
1 heavy task 395msec 406msec 387msec

やはり通信のオーバーヘッドはWebWorkerの方が最適化されていますね。

SubWorkerについて

他のブラウザでは未確認ですが、ChromeではWorker内でWorkerを作る事が出来ません。実は今回はこの現象のためiframeをWebWorker代わりに使おうとして両者の比較を行う事になりました。仕様上はSubWorkerを作成する事が出来るようですので、今後に期待ですね。2年以上放置されているようですが、、

参考

onloadの扱い

Chromeでのみ確認しましたがちょっとイレギュラーな動作となりました。

  • WebWorker
    onloadのタイミングをJavascript側で意識する必要はありません。Worker起動時の処理中にpostMessageすると、処理が終わってからmessageイベントが発生します。
  • WebMessaging(iframe)
    $iframe.onload後でないと、postMessageが拾われません。
  • WebMessaging(window)
    window.onload後でないと、postMessageが拾われません。

コンソール出力

Workerプロセス内ではconsole.log()などのデバッグ用の関数が使えません。なんだかんだでこれが開発する上で一番大きな違いな気もします。

ノーバート・ウィーナーの自伝

最近ノーバート・ウィーナーの自伝、「神童から俗人へ」を読んだので、内容について少し残しておこうと思います。

 

彼はサイバネティクスと言う学問を作り出した20世紀の学者です。現在の情報通信技術の礎を築いた人物の一人として、情報技術に教養のある現代の技術者なら名前を聞いたことがあるであろう、そんな人です。

本書では彼の業績の中身にはほとんど触れず、生まれてから、どういう経緯で30才過ぎにMITの教授に就いたかを時系列に沿って記してあります。

 

思い切って三行にまとめてみますと、

  • ユダヤ系アメリカ人として1894年に生まれる
  • 言語学者であった父親にスパルタ教育を受けて、15歳でハーバード大学院に通う
  • 父親には哲学を志すよう強いプレッシャーを受けたが、最終的には数学の世界に身をおくことになる

大体こんな感じです。

本書は非常に論理的に記述されており、また3才ごろの描写であっても固有名詞がバンバンでてくる、その記憶力には驚かされます。そんな彼について生来の俗人であるぼくには気の聞いたコメントは出来ないので、彼が生きた時代に焦点を当てて印象的だった内容を2点紹介してます。

 

20世紀初頭のアメリカとヨーロッパ

彼が物心ついてから青年となって行く時代はユダヤ人に対する風当たりがアメリカでもきつかったようです。ユダヤといえばナチス、反ナチスといえば連合国=アメリカと連想されるので、意外でした。今やユダヤはアメリカにおいて政治力を握っているといわれていますが、その苦渋の歴史がうかがえました。

一方、一次大戦のころはボストンの学者の間では「r」を発音できないドイツ風をふかしたスタイルが流行だったそうです。これも今では考えられないですよね。つまり当時のアメリカは学会は、ヨーロッパから見ると二流だったのです。確かに南北戦争が終わってから1世代とちょっと巡ったくらいの時期なので頷けます。

こうして見ると20世紀においていかにアメリカが変わったのかが分かります。反面ドイツは今も昔も影響力の大きな強国ですね。

 

 第一次大戦

もし現在ぼくが徴兵されて、「戦場に行って来い」と言われたらかなり辛いです。アメリカでも戦場から帰ってきた兵士がPSTDにより苦しんでいたりすることが報道されていたり、世界的に戦争に対するイメージはかなり悪いですよね。

時代が第一次大戦に突入して戦争ムードがアメリカ国内で出てきたころ、ノーバートは軍隊を志願します。彼は決して血気盛んな、愛国心が高い若者とは本書では描かれておらず、むしろ内気で思慮深い少年といったイメージです。そんな彼が兵役に何度も志願して、適正試験でよい結果が出せずに苦悩していたそうです。

ユダヤ人である彼がドイツのユダヤ排斥主義に対して戦争の意義を感じたのでしょうか?詳しくは本書からは分かりません。ただ当時は今と戦争に対するイメージが大きく違っていたようです。

 

全体として淡々と事実を並べて、客観的な文章で進めていく本書はいかにも数学者の自伝といった雰囲気が出ており、読み進めていくだけでも頭の体操になりそうです。ただ本書の最後に書かれた後の彼の妻との馴れ初めを読み終えて本を閉じると、なんかほっとしました。

 

神童から俗人へ

神童から俗人へ

AngularJSでの非同期処理

1/26に開催されたAngularJSハッカソンに参加してきました。

ハッカソンは初めてでしたが、スタッフの方やチームに恵まれエキサイティングな一日でした。中でも新鮮だったのは、Dropbox上に作業エリアを作ると共同作業がはかどることです。今後もお世話になりそうです。

今回はチーム編成の都合上サーバーサイドの担当だったので、目当てのAngular.jsにはほとんど触れませんでした。そのため復習がてら本家のTutorial を通していくつか引っかかった点を調査してまとめました。

Controllerで非同期処理を扱う

以下のコードでは、“Change the world!”と表示されることを期待していたのですが、実際は“Hello world!”と表示されます。どうしてでしょうか?

  • index.html
<div ng-controller="MainCtrl"> 
  <p>{{title}}</p> 
</div>
  • app.js
var MainCtrl = function($scope){ 
  $scope.title = “Hello world!”; 
  setTimeout(function(){ 
    $scope.title = “Change the world!”; // 実行後Viewが更新されない 
  }, 0); 
}

チュートリアル には以下のようにあります。

Once an application is bootstrapped, it will then wait for incoming browser events (such as mouse click, key press or incoming HTTP response) that might change the model.

アプリは起動するとモデルを変更するようなブラウザイベント(クリックや、キー入力、Httpレスポンスなど)を待ちます。

つまりAngularでイベントを発生させないとModelとViewは同期されないようです。そのためController側で非同期処理を走らせてModelを変更したいときはAngularが用意しているモジュールを使いましょう。Ajaxには$httpを、setTimeoutなどの遅延処理には$timeoutなどです。

  • app.js
var MainCtrl = function($scope, $timeout){ 
  $scope.title = “Hello world!”; 
  $timeout(function(){ 
    $scope.title = “Change the world!”; // 実行後Viewが更新される 
  }, 0); 
}

モジュールのインポート動作

AngularはDependency Injection(DI)パターンを採用しているため、インポートではなくinjectと呼ぶのが正確かもしれませんが、分かりやすさのためにここではインポートと言うことにします。

デフォルトでは、モジュールはControllerの引数名にしたがってインポートされます。例えば上記の例を以下のようにしても、同じ変数に同じモジュールがインポートされます。

var MainCtrl = function($timeout, $scope){

逆に$timeoutaなど、不適切な引数名をここに入れるとエラーになります。ここちょっと不思議じゃないですか?変数名を取得するなんてそんなメタなプログラムどうやって書いてるんでしょう?答えは以下のannotate関数にあります。

https://github.com/angular/angular.js/blob/master/src/auto/injector.js

見てびっくりしたんですが、関数名をtoString()してから引数名をパースしてるんですね。よくこんな事思いつくもんだなぁと感心しました。

またClosure Compilerで最適化するときなど、引数名を変更したい場合は以下のようにすればOKです。

MainCtrl.$inject = [’$scope’, ’$timeout’];

その他雑感

従来のViewとModelの分離は、Javascript側にDOMセレクターなどを押し込め、HTML側のJavascriptコードを排除する事に重点が置かれていました。Angularはアプローチが逆で、Javascript側からDOM情報を排除する代わりにHTML側からJavascriptで使う変数名やメソッドなどを指定しています。

これは非常に理にかなっていて、無数のグローバル変数であるDOM要素をJavascript側から指定するよりも、スコープ内に閉じ込められた変数をHTML側で指定する方がシンプルになるのは自明です。反面、Javascript側でガンガンDOM要素を生成するような場合とは相性が悪いように思います。

実際はjQueryなどのライブラリと併用して使う事が想定されているので問題は起こりませんが、jQuery使えるならそれでいいじゃないかと言う声も現場では大きいかもしれません。ともあれこのような野心的な試みには思わずエールを送りたくなります。ソースコードも綺麗ですし今後の進展が楽しみですね。

Windows上のSeleniumからWebDriverで定期的にブラウザを立ち上げる

Windows7SeleniumのWebDriver経由でChromeを定期的に立ちあげてテストする際に嵌ったのでメモっておきます。なおWindowsXPでも動作確認できました。

嵌りどころ

Windowsではサービスとしてcronなどのdaemonを起動させると、そのプロセスからはGUIアプリケーションを立ちあげて動作させることが出来ない制約があります。以下の記事では迂回する手段を紹介していますが、daemon自体に手を加える必要があるので断念しました。

http://owlsperspective.blogspot.jp/2010/01/start-gui-process-from-service.html

困っていたところ「タスクスケジューラからならGUI立ち上がるよ」と、cygwinのMLにアドバイスがありました。

http://cygwin.com/ml/cygwin/2012-08/msg00228.html

なのでちょっと荒いやり方ですが、タスクスケジューラにdaemonを監視させてプロセスを起動してやることで今回は対応しました。タスクスケジューラから直接ジョブをキックしても良かったんですが、設定UIが使いづらいので1枚かませました。

利用したもの

Jenkinsのジョブに登録しておくpythonスクリプトの例です。

from selenium import webdriver

url = “http://www.google.co.jp/”
d = webdriver.Chrome()
d.get(url);
location = d.execute_script(“return document.location+’’;”)
if location == url:
  print ’success’
d.close()

定期ジョブ管理にpycronやcron(cygwin)を使うことも検討しましたが、pycronでは文字エンコーディングが崩れたり、cronはcygwin経由が使いづらかったりで、結局Jenkinsが一番楽でした。

今後の課題

今回はWindows縛りだったのでこのような方法を取りましたが、Linuxの場合はどうなるのか試していません。またサービスからWebDriverを立ち上げたとき挙動についても、どうなるのか把握できていないので今後の課題としておきます。