2010-11-08
■ [ubuntu] ubuntu + mozc + azik
LinuxのmozcでAZIK入力ができるようにした。
なんかibusからmozcの設定ができなかったので以下の手順で。
$ sudo aptitude install mozc-utils-gui
これで/lib/mozc/mozc_toolが入る(のだと思う)
$ /usr/lib/mozc/mozc_tool --mode=config_dialog
これで設定画面が出る。情報元
http://miraicorp.blog90.fc2.com/blog-entry-396.html からGOOGLE_AZIK.txtをダウンロードし、mozcに食わせる。
ubuntu 10.10だとデフォルトはibus-mozcだが、scim-mozcでもuim-mozcでも同じようにいけるんじゃないかな?
(12/8 追記: ibusの設定で言語パネルが出るようにしておくと、言語パネルの「→」マークからmozcの設定画面を出せるようだ。)
2010-11-16
■ [ruby] Seattle.rb推奨の「gem名の命名規則」
- 基本的にアンダースコアで単語を区切る
- 既存のgemに機能を追加するもの(autotest-growlとか)の場合のみ、ハイフンで区切る
- 大文字は使わない(case-insensitiveなOSのため)
最後の理由は、例えばWindows上だとrequire 'ZenTest'をrequire 'zentest'と書いても通っちゃうみたいに、初心者が意図せずプラットフォーム依存なコードを書いてしまう危険性があるからとのこと。
Rubyの標準添付ライブラリも、そろそろ命名規則を統一した方がいいんじゃないかと思ったりもする(tempfileとtmpdirとか)。
■ [golang][book] 「はじめてのGo言語」を読んだ
4777515591
Googleから公開されたプログラミング言語「Go」の、日本初(世界初?)の解説本。Goの言語機能について 一通り書いてある模様。
著者が若いこともあって*1、文章が分かりにくかったり記述が怪しいところもあるけど、 Go言語の概要を手っ取り早く知りたいという向きには良いだろう。 特にGoはC言語に似ているようで、いろんなところが微妙にリファインされていたり、例外機能が独特だったりするので、 英語文書を読む前に日本語で概要を眺められるのは有り難い。
あと、Effective Go(和訳)みたいに「シグネチャ」「リエントラント」とか小難しい単語が出てこない分、 授業でC言語を習ったばかりの学生さんとかにはかえって読みやすいかも知れない。
Go言語の感想
一言でいうと、「C言語を作り直して、並列機能を入れたもの」という感じ。
用途としては、ハードウェアに近いところを触って性能を出さないといけないようなものになるんだろうなぁと思う。 性能が要らないならスクリプト言語でいいわけだし。Webサーバとか、動画エンコーダとか?
Cから良くなった点:
- セミコロンが省略可能
- if,forの括弧も不要
- 宣言と代入が別演算子
- ポインタ演算はできない
- えらいswitch
- デフォルトでfallthroughせず、breakが不要
- caseに値を複数書ける
- 式なしswitchがある(Rubyの式なしcaseみたいな)
便利そうだった点:
- 複数の値を返せる
- 多重代入
- 辞書型
あとちょっと面白いのは、「オブジェクト指向のようなもの」があるところ。オブジェクト指向といってもクラスベースではなくて、 *2 構造体を第一引数に取る関数を「メソッド」と呼んでいる感じ。データとその操作が分かれていると考えるとCLOSとかHaskellを連想するけど、 Goのメソッドはobj.Func()のような書き方ができるのでそこだけ普通っぽい。
並列機能(Goroutine)は、Erlangみたいなやつですねという感想(短い)。
気になったところとか
正誤表が見つからないのでとりあえずここに書く。
- null(p.39)とnilがどういうものなのか書いていない(ってかnullは誤記ですね)
- 実行結果の冒頭に「>」(例:p.93)とか「>>」が付いているものがある(何も付けないほうがいいと思う。付けるなら最初の章で説明すべき)
- 「レシーバ」と「メソッド」を間違えている箇所がある(例:p.78)
- 人工的な例が多いので、PointとかAnimalとかFruitsとかでも良いから、意味のあるプログラム例だと良かった。そうすると3-2とかはずっと読みやすくなると思う。適切な例を考えるのは難しいけどね。
- p.73のプログラム例はfuga.Add()が抜けているのでは?
- p.67 occordという英単語はない(occurred?) *3
- 「表わす」は「表す」の方が一般的かなと思う(間違いではないようだけど)
出版前に誰かに見てもらいたいときは、ネットでレビュアーを募るのも手です。 WEB+DB PRESSのRuby連載は、今のところ@tsuyoshikawaさん(第一回/Sinatra)、@nalshさん(第二回/Ruby 1.9)、@mat_akiさん(第三回/Heroku)に 見てもらっています。ご協力に感謝。
あとこれは出版社側の話だけど
- ソースコード中の「_」のフォントがおかしい
- ソースコード中の「fl」「fi」は合字にすべきでない
2010-11-29
■ [ruby][event] Ruby Advent Calendar 2010の参加者募集中です
あのRuby Advent Calendar(jp: 2009)が帰ってきた!
Advent Calendarは、12月のクリスマスまでを数えるカレンダーで、1日に1つずつ穴を開けていく感じのものです。ものによっては中にお菓子が入っていたりします。
それになぞらえて、1日に1つずつRubyに関するTipsを書いていくのがRuby Advent Calendarです。参加方法は、ATNDで登録して、担当日に自分のブログに記事を投稿するだけです。3行でもいいので、ぜひ書いてみてください。
英語トラック
今年はJPerl Advent Calendar 2010 - English Trackにならって、英語トラック(http://atnd.org/events/10439 )もあります。 25人集まるのか分からないですけど、去年の各種Advent Calendarを見ると25人いかなかったのもあるので、それでもいいかなと思って立ててみました。
The English / Japanese barrier hides the existence of rabbit, qwik and tdiary you should know about.
[Twitter - yuguiより引用]
というのはyuguiさんのpostですが、日本から英語圏への発信がもっと上手くいくようになればいいなと思っています(最近だと rubyflowに投稿するという手があったりしますけど)。■ [javascript] JavaScriptのプロトタイプベースオブジェクト指向をRubyと比較する
JavaScriptはプロトタイプベースのオブジェクト指向言語で、RubyやJavaにあるような「クラス」というものがありません。 しかし、プロトタイプをうまく使うことで、クラスベースのオブジェクト指向に近いことができます。
というわけで、RubyとJavaScriptを比較してみました。「もしJavaScriptがクラスベースオブジェクト指向言語だったら」:
| Ruby | JavaScript | ||
|---|---|---|---|
| 名称 | クラス | コンストラクタ | |
| 定義 | class Foo | var Foo = function(){... | |
| インスタンス生成 | Foo.new() | new Foo() | |
| 初期化方法 | def initialize() | function Foo() | |
| 自分のクラスの取得 | foo.class (=> Foo) | foo.constructor (=> Foo) | |
| インスタンスかどうか | foo.instance_of?(Foo) (=> true) | foo instanceof Foo (=> true) | |
| メソッド | |||
| クラスメソッド | def self.do_something() | Foo.doSomething = function(){... | |
| Foo.do_something() | Foo.doSomething(); | ||
| インスタンスメソッド | def something() | Foo.prototype.something = function(){... | |
| foo.something() | foo.something(); | ||
| 特異メソッド | def foo.do_special() | foo.do_special = function(){... | |
| foo.do_special() | foo.do_special(); | ||
| 継承 | |||
| サブクラスの定義 | class Apple < Fruit | Apple = function(){}; Apple.prototype = new Fruit(); | |
以下解説です。JS記事久々だし嘘があるかも知れません…。
JSのコンストラクタはクラスに近い
前述のようにJavaScriptにはクラスがありませんが、 コンストラクタ(オブジェクトの生成・初期化に使われる関数)がクラスに近い役割を持ちます。
クラスメソッドやクラス定数のようにクラスに属するものは、コンストラクタ自身に 定義されます(例:Foo.CONST = 1)。JavaScriptでは関数もオブジェクトなので、任意のプロパティを追加することができることを利用しています。
インスタンスメソッドやインスタンスプロパティのように、インスタンスに属するものは、Foo.prototypeにまとめて定義されています。つまり、Foo.prototypeはFooのインスタンスの原型である…という意味で、prototypeという名前が付けられているのだと思います。
プロトタイプはメソッド呼出しのときに使われる
ここからは、fooに対するFoo.prototypeのことを「fooのプロトタイプ」と書きます(日本語は便利ですね)。文字列"a"のプロトタイプはString.prototypeです。配列[1,2,3]のプロトタイプはArray.prototypeです。関数function(){}のプロトタイプはFunction.prototypeです。オブジェクト{a: 1}のプロトタイプはObject.prototypeです。 *1
foo.method()という呼出しがあったとき、まずfoo自身がmethodという名前の関数を持っているかどうかがチェックされます。これはRubyでいう特異メソッドに相当します。で、存在しなければ、fooのプロトタイプのmethodが使われます。つまりFoo.prototype.methodですね。このように、メソッド呼出し時にプロトタイプをチェックすることで、インスタンスメソッドの呼出しが実現されています。
さて、ここまでは良いでしょうか?(オライリーのJavaScript 第5版 第9章を読むと、もっと丁寧な説明があります)
4873113296
単一継承を実現する
ここから、JavaScriptで「継承」を表現する方法に入ります。
foo.toString()というメソッド呼出しを考えます。fooがtoStringという関数を持たない場合、fooのプロトタイプのtoString(つまりFoo.prototype.toString)が探されます。ではこれも存在しなかった場合はどうなるでしょうか?このような時は、Foo.prototypeのプロトタイプから探されることになっています。インスタンスメソッド群をFoo.protoype = {...}のような形式で定義していたとすれば、Foo.protoypeはObjectのインスタンスですから、Object.protoypeからtoStringを探すことになります(そしてObject.protoypeにはtoStringが存在するので、それが呼ばれます)。
toStringの探索順序をまとめると、foo→Foo.protoype→Object.protoypeのようになっています。これは、「FooがObjectのインスタンスメソッドを継承している」という風に見ることができます。 普通に「function Foo()」のように宣言した場合、Foo.prototypeにはObjectの直接のインスタンスが設定されることになっているので、「デフォルトの親クラスはObjectである」と言えます。
これを応用して、コンストラクタのprotoype属性を適切に設定してやることで、ユーザクラス間の継承も実現できます。例えばFruitのサブクラスAppleを定義したいときは、Apple.protoype = new Fruit(); とすれば、Apple.protoypeのプロトタイプ == Fruit.protoypeとなるので、インスタンスメソッドの探索順序がApple.protoype→Fruit.protoype→Object.prototypeのようになります。 *2
現実には…
これでインスタンスメソッドの継承は実現できましたが、これだけだとコンストラクタ内の処理は継承されないので、明示的に
function Apple(price){
Fruit.call(this, price);
}
のように呼び出すか、
function Apple(price){
this.superclass(price);
}
Apple.prototype.superclass = Fruit;
などと*3してやる必要があります。
こんな感じで、「class Apple < Fruit」ほど簡単にはクラスベースOOP的な継承を行うことはできないようです。 フレームワークによっては、Class.create(Prototype.js)や$.extend(jQuery) など、継承を助ける機能が用意されています。
*1 ちなみにあるインスタンスのプロトタイプを取得する書き方はfoo.__proto__とかObject.getPropertyOf(foo)とかがありますが、いずれも環境依存です。通常はfoo.constructor.prototypeで取得できますが、これはfooの生成後にconstructorとかそのprototypeを変更したりすると実際に使われるプロトタイプとずれてしまいます
*2 環境依存かつobsoleteですが、環境によってはより直接的に「Apple.prototype.__proto__ = Fruit.prototype;」と書けるようです
*3 オライリー本より。見た目的にはいいが、superclassがインスタンスプロパティってのはちょっと気持ち悪いよね
2010-11-30
■ [javascript] パッケージマネージャを備えたサーバサイドJavaScript環境、node.js
node.jsは最近勢いのあるサーバサイドJavaScript環境である。インタプリタにはGoogle ChromeのV8を使用している。
売りとしては「イベント駆動なHTTPサーバが書けるのでCometとかWebSocketのサーバ側に最適」という話なのだが、個人的な用途ではそれは別にRuby+EventMachineとかでいいので、 むしろパッケージマネージャ(npm)を備えたサーバサイドJS環境ができて、JSをRubyとかPerlみたいに使えますよ、という点が面白いと思った。
インストール
port install nodeとか、brew install nodeとか。
パッケージ管理
前述のnpmを入れると、RubyGemsみたいにnpm install fooでパッケージを追加することができる。
モジュール管理
JavaScriptには標準のモジュール管理機構がないが、node.jsはCommonJSという仕様に準拠したモジュール機能を備えている。
定義側が「exports = Foo」、呼び出し側が「var Foo = require('foo')」みたいな感じ。この辺は https://github.com/visionmedia/jade とかの実際のライブラリを見るのが早いかと思う。
ちなみにCommonJSは単にJavaScriptのファイル間の依存関係を指定する方法なので、利用先はnode.jsに限らない。例えばRequireJSというライブラリを使うとブラウザ上でも使用できるようだ。
(追記:CommonJSはモジュールに限らず、さまざまな仕様の共通化を目指しているようだ: http://wiki.commonjs.org/wiki/CommonJS あとnode.jsとRequireJSはAPIが違った)
余談
修論で作ったBiwaTuples(こんな名前だっけか)のサーバ側はGauche+スレッドで書いてたんだけど、むしろnode.jsで実装した方が素直な構成なんじゃないか?と思ったのだった。 素直かどうかはともかく、スレッド使ってたのをイベント駆動で書き直すとどんな感じになるのかはちょっと興味がある。
■ [javascript] CommonJS準拠の依存関係解決ライブラリについて
もう少し調査した。
まずCommonJSはいくつかの仕様の集まりで、node.jsはModules/1.0を実装していて、 RequireJSはModules/AsynchronousDefinitionを実装しているのでAPIが違ったようだ。
サーバサイド・クライアントサイドの両方で同じAPIを使いたい場合は(という要求がどれくらいあるか分からんが)、 クライアントサイドでModules/1.0が使えるライブラリか、 サーバサイドでModules/AsynchronousDefinitionが使えるライブラリを探せば良いことになる。
CommonJSの準拠実装一覧を見ると、前者にはJSBuildと yabbleが、 後者にはnodulesが該当する。
Modules/1.0とModules/AsynchronousDefinitionの違いは、前者がrequire()で後者がdefine()ととりあえず覚えておく(つまりよく分かってない)。
実行効率で言えば、YUI.Compressorとかで1ファイルにコンパイルするのが一番いいんだけど。
追記1
- 「ライブラリを読み終わってから、HTML内のscriptタグを実行する」みたいな用途はAsyncじゃないと駄目なのかも (全てを*.jsファイルにすればModules/1.0でいいが)
- node.jsはAsyncの方は非対応なので、サーバ側nodules+クライアント側RequireJSという構成になるか。めんどいな。
ちなみにもっと単純なのでよければ http://labjs.com/documentation.php というのがある。
追記2
- Asyncな読み込みの方はまだ仕様が固まってなくて、APIがうまく揃わなかった。まだ早いか。
- productionでは1ファイルにコンパイルする前提なら、クライアント側はLABjsでシーケンシャルに読み込んで、サーバ側ではファイルを直接開いてevalとかで普通にいけそうな気がしてきた。
