Ruby の Ubuntu 12.4 へのインストール

Virtual Box に Ubuntu 12.4 を入れて、それに rbenv で各種Ruby をインストールしたので、その方法のメモ。

sudo aptitude install libssl-dev libyaml-dev libreadline-dev zlib1g-dev
sudo aptitude install libncurses5-dev libgdbm-dev tk-dev

# for maglev
sudo aptitude install build-essential

# for java
sudo aptitude install openjdk-7-jre-headless openjdk-7-jdk

# for git
sudo aptitude install git-all

# for rbenv
sudo aptitude install rbenv

# for ruby-build
cd
git clone git://github.com/sstephenson/ruby-build.git
cd ruby-build
./install.sh

# install all rubies
ls -1 /usr/local/share/ruby-build/ | xargs -idir basename dir| xargs -iversion rbenv install version
rbenv versions
# 以下、出力結果
  1.8.7-p352
  1.8.7-p357
  1.8.7-p358
  1.8.7-p370
  1.9.1-p378
  1.9.2-p180
  1.9.2-p290
  1.9.2-p318
  1.9.2-p320
  1.9.3-dev
  1.9.3-p0
  1.9.3-p125
  1.9.3-p194
  1.9.3-preview1
  1.9.3-rc1
  2.0.0-dev
  jruby-1.6.3
  jruby-1.6.4
  jruby-1.6.5
  jruby-1.6.5.1
  jruby-1.6.6
  jruby-1.6.7
  jruby-1.6.7.2
  maglev-1.0.0

Google の新言語 Dart

Google の新言語 Dart でいろいろ遊んでみた。

予約語のように思えた abstract、class、static 、 final 、 get なんかが予約語じゃなくてびっくりした。JavaScript からのポーティングを容易にするためなんだって!本気で JavaScript の置き換え目指しているんだな。

ちょっと勉強しただけだけど下記のような点が印象に残った。
 ・ 演算子オーバーロードがある
 ・ Generics を使える
 ・ 静的型言語と動的型言語の両方の書き方ができる。
  ・ Dynamic 型とかいいね。
 ・ シングルクオート3つとかダブルクオート3つの複数行文字列がある
 ・ 文字列中に ${任意の式} のように書く String Interpolation が可能
 ・ 数は int 型と double 型
  ・ int は int32_t でも int64_t でもなく任意の長整数を表現可能
 ・ 暗黙の型変換が boolean conversion 以外にない
  ・ JavaScript とは違う
 ・ 単に int i と書いた場合は、i は 0 ではなく null
 ・ ちゃんと closure は使える
 ・ static メソッドとか static 変数は override したり hide したりできない
  ・ 継承するクラスは、基底クラスの内部実装も気にせなあかんということなんかな
 ・ 常に単一スレッドで動く
  ・ スレッドの概念がない代わりに isolates という概念がある
  ・ isolates は Erlang のプロセスみたいなもの?

ライブラリの方も興味深い。
 ・ 普通に num 型にメソッドがある。Ruby みたいなかんじ
  ・ 100.toRadixString(16) が "64" になるみたいな書き方
 ・ 文字列連結のための StringBuffer 型、immutable な String 型がある
 ・ Queue は Double Ended Queue
  ・ 最初の要素を取り出すのは shift() ではなく removeFirst()
  ・ 最後の要素を取り出すのは pop() ではなく removeLast()
  ・ メソッドオーバーロードで << を再定義したくなるかんじ
 ・ RegExp クラスがある。使い方はめんどそう。

RegExp exp = const RegExp(@"(\w+)");
String str = "Parse my string";
Iterable matches = exp.allMatches(str, exp);

 ・そういや、String クラスが Pattern インタフェースを実装している
  ・ String クラスでも 上の allMatches() メソッドが使えるみたい。
 ・ Collection インタフェースに foreach() メソッドとかがある。
  ・ List クラス、Queue クラス、Set クラスとかで使える
 ・ Promise クラスがある。JSDeferred みたいなかんじ?
 ・ Dispatcher、Isolate 、ReceivePort 、SendPort が面白そう

けど、いろいろやってみたけど私だったら Dart を使わず、Coffee Script を使うかなぁ。
理由は、
 ・ JavaScript のオブジェクトと挙動が全然違う

main(){
  var obj = {};
  obj["attribute"] = 1;
  print(obj["attribute"]); // 正常実行される
  print(obj.attribute); // 失敗する
}

オープンクラスじゃないから既存のクラスにメソッド追加とかはできない
・ オブジェクトにメソッド追加とかもできない
・ "と'の違いじゃなくて、 @ で string interpolation の有無を区別する

main(){
  var world = "World!";
  print("Hello, ${world}"); // Hello, World!
  print(@"Hello, ${world}");  // Hello, ${world}
  print('Hello, ${world}'); // Hello, World!
  print(@'Hello, ${world}');  // Hello, ${world}
}

 ・メタプログラミング的なことができない
  ・ せめて、typeof くらいは欲しいんだけど・・・。
  ・ for(var i in obj) でオブジェクトの要素を取得することもできない
  ・ foreach はあるけど、Java 的なイテレータのための Syntax sugar
 ・DSL向けじゃない
  ・ CoffeeScript は、() をわりと省略できるのが気に入っていたり。
 ・; を忘れたらバッチリ怒られる。
  ・ めんどい

全体的に、一人で JavaScript を書く程度のレベルであれば発生しないようなコーディング規約とか、他人のソースコードを読めない的な問題を解決するために作られた言語という印象。

Java の人は豊富にいるけど、JavaScript の人はあんましいない開発陣でチーム開発する場合とかは向いているのかもしんない。
JavaScript 技術力が高い開発者だったら、JavaScript でできるのに Dart でできないことがいっぱいあることが気になっちゃいそう。

メタプログラミングRuby読書会 第2回

3月5日にメタプログラミングRuby読書会を実施しました。

メタプログラミングRuby の中で、カレントクラスという用語が説明されていましたが、
説明が分かりにくいように感じたので新たに整理していこうと思います。

カレントクラスとは、def method_name args ... end のような書き方で、メソッドが定義される場所のことです。

カレントクラスは次のように考えることができます。
- クラスのコンテキストであれば、現在のクラス
- オブジェクトのコンテキストであれば、self のオブジェクトの特異クラス

クラスのコンテキストに遷移する方法は次の2通りあり、その場合はそのクラスがカレントクラスになります。
- class または module キーワードでクラス(モジュール)をオープンする
- class_eval でレシーバのクラスをオープンする

逆にオブジェクトのコンテキストに遷移するには、instance_eval を使うことになります。この場合はそのオブジェクトの特異クラスがカレントクラスになります
つまり、 instance_eval の中の def はそのオブジェクトの特異メソッド定義になります

クラスのコンテキストへの遷移の中で特に、class <

# (1) トップレベルのメソッド定義( Object に定義される)
def toplevel_method
end

# (2) クラスのコンテキストでのメソッド定義
#     クラスA のインスタンスメソッドとして定義される
class A 
  def instance_method1
  end
end

# (3) class_eval を利用してクラスのコンテキストでメソッド定義
#     クラスA のインスタンスメソッドとして定義される
A.class_eval do
  def instance_method2
  end
end

# (4) 特異クラスのコンテキストで実行するための記法 <

LiveCoding で 解説

cuzic です。

もう先週のことですが、LiveCoding#10 に参加してきたら、突然 解説を依頼され、解説してきました。

イベント内容は、yhara さんと nari さんのすごいギークがコーディングするのをみんなで見よう!みたいなもので、最近は sixeight さんが中心に非常に熱気を持って実施されています。

LiveCoding#10 では「プロの変な言語作者」yhara さんと、「日本のガーベッジコレクション界の権威」 nari さんが最強タッグを組んで、新しい言語をわずか40分で実装するというものでした。

yhara さんの整数や文字列を含めてすべてを配列で表現するという新言語にはちょっとドギモを抜かれました。

変な言語にはいろいろとありますが、そこまで限定をするという発想にはびっくりしました。

40分時間があるとはいえ、ちゃんとテストを書きながらコードを書いていた点も感銘を受けました。自分のスタイルへのこだわりを感じます。

ガーベージコレクションについては基本的な原理などは一通り勉強したことはあるものの、実際のコードについては、ちゃんと見て勉強したことなどはあまりなかったので、今回の企画のようにコンパクトなガーベッジコレクション実装を実際に作成しているところを見ることができたのは、大変勉強になりました。

私の解説についてですが、突然の依頼で準備が足りず、聞き苦しかった部分もあったかと思うのですが、多くの方から好評いただいていたようで、よかったです。

Ruby でクラス定義の DSL 作成

cuzic です。

今日も Ruby の話題です。

理由はないのですが、大林さんの昔出した課題のような問題に取り組んでみました。

目標は、

  A = AttrClass :accessor, :with_default => 1 do
    def initialize
      puts "initialized"
    end

    def do_something
      puts "do_something"
    end
  end
  a = A.new #=> intialized
  p a.accessor #=> nil
  a.accessor = "some value"
  p a.accessor #=> "some value"
  p a.with_default #=> 1
  a.with_default = 2
  p a.with_default #=> 2
  a.do_something #=> do_something

となるような AttrClass メソッドを定義することです。

つまり、AttrClass メソッドの呼び出しが下記のコードと等価になるようにする、ということです。

 class A
   attr_accessor :accessor
   attr_accessor :with_default 
   def initialize
     @with_default = 1
     puts "initialized"
   end

   def do_something
     puts "do_something"
   end
 end

これはやってみると、比較的簡単にできました。
次のようなメソッド定義になります。

def AttrClass *symbols, &block
  Class.new do |klass|
    symbols.each do |sym|
      case sym
      when Symbol
        attr_accessor sym
      when Hash
        klass.class_eval do
          sym.each do |key, value|
            attr_accessor key
          end
        end
        Module.new do
          new_original = klass.method :new
          define_method :new do |*args, &block|
            obj = new_original.call *args, &block
            sym.each do |key, value|
              obj.__send__ "#{key}=", value
            end
            obj
          end
          extend_object klass
        end
      end
    end
    klass.class_eval &block
    klass
  end
end

ポイントは、Class#class_eval を使って、Class のコンテキストでブロックを評価していることや、new クラスメソツドを再定義して、インスタンス変数の初期化を行っているところでしょうか。

これを使えば、アクセサなどが多いクラス定義がより簡潔に書けます。

Rubyのドキュメンテーション YARD編 (1)

cuzic です。

WMI でいろいろとプロパティなどを観察していて、Description という Qualifier でその WMI クラスのプロパティに関する詳細な説明が得られることに気がつきました。

簡単な例としては、

    require 'win32ole'
    loc = WIN32OLE.new("WbemScripting.SWbemLocator")
    service = loc.ConnectServer

    service.SubclassesOf("", 131072).each do |klass|
      desc = klass.Qualifiers_.Item("Description") rescue nil
      puts "#{klass.Name} #{desc}\n" if desc
    end

とすると、さまざまな WMI クラスの説明を表示できます。131072 (= 0x20_000)

プロパティ、メソッド、メソッドの引数などについて、Description の Qualifier が設定されているため、ドキュメントとして、十分な情報が得られます。

そこで、Ruby のドキュメント作成方法について学ぶための題材として WMI の Description の Qualifier が使うというアイデアを思いついてみました。

まずは、Ruby のリファレンスマニュアルとして使われている bitclust を利用して、ドキュメントの作成を検討してみたのですが、どうも標準ライブラリが前提からなのか、やり方がよく分かりませんでした。
次に、Ruby でよく使われているドキュメント作成ツールである RDoc を採用しようと思ったのですが、パラメータ引数の説明の書き方などがよく分からなかったり、attr_reader とかと、メソッド定義をいい感じに区別して表示させたかったのですが、やり方を見つけられませんでした。

次に試したのは、RDoc の後継(?)の YARD です。YARD を使うとやりたいことが一通りできそうな上、書き方が私にとって、すんなり理解できたのですぐに気に入りました。

  ##
  #  Caption プロパティは、オブジェクトについての簡単な説明 (1 行分の文字列) です。
  # @return [string] Caption
  attr_reader :Caption

のように、@return や、@param のような JavaDoc の書き方は見慣れていて、すんなりついていけます。

そこで、YARD を使って WMI のドキュメントを作成してみました。ここにおいてみています。

YARD を使ってみて、思ったことは、

  • デフォルトの色合いとかはけっこうそつがないかんじで、見やすい
  • カスタマイズは柔軟そう。ドキュメントもいろいろと書かれていて、探求する価値がありそうです。
  • 生成がとても遅い。今回はかなりの分量があったせいかもしれませんが10分以上かかってびっくりしました。

といったところです。

YARDは拡張性やカスタマイズが容易そうな印象なので、そのあたりについても探求していきたいな、と思いました。

プログラミングの心理学 − 読了

cuzic です。

大昔に買っていた本であるプログラミングの心理学 を読み終えました。

プログラミングの心理学―または、ハイテクノロジーの人間学 25周年記念版

プログラミングの心理学―または、ハイテクノロジーの人間学 25周年記念版

昔にも読み終えた本なんだけど最近また読みたいな、思って読み返したのです。

印象に残った文章を箇条書きで引用します。

  • プログラムが動かないなら、実行効率とか適応力とか開発費用とかいった尺度はなんの意味も持たない
  • フィッシャーの基本定理「システムは特定の環境によく適応していればいるほど、新しい環境には適応しにくくなる」
  • いまなお多くの管理職はすべてを求めたがり、最良の製品を得るために懸命なトレードオフを見出すことの重要性を理解していない。だが、それはすべてのバッターにはホームランを打てと命じ、すべてのピッチャーにはすべてのバッターを三振にとれと命じれば、ニューヨーク・ヤンキーズの監督が務まる、と思うも同然である。
  • 彼らのあまりに多くがいまだに「悪者発見方式」にこだわっている。それは間違いなく人々を真の原因を隠すように仕向ける。
  • ホーソン効果を利用するときわめて大きな実際的価値がある、ということを知った。(中略)私は管理の心理学に関する1つの基本原理を発見した。それは「人々に注意を向ける管理者はよい結果を得る」ということだった。
  • たたき上げのプログラミング管理者はとかく組織図を過度に信頼し、自分たちが現場にいたときに実にうまく活用していたより非公式な機構を軽視したがるようだ。
  • 非公式的機構は必ず存在する。それを理解せずに物事を変更するのは危険だ。(中略)しばしばそういうことは物理的な配置を換えることにより起こる。
  • 「所有指向」のプログラミングの真の問題点は、別のところから生じる。(中略)自分のプログラムを自分のエゴの延長部だと本気で思っているプログラマは、そのプログラムに含まれる誤りを全部見つけてやろうと頑張ることなどしないであろう。(中略)無視しようのない完全な失敗でなかった場合には、認知的不協和の解消はもっと容易である。誤りがそこにあることを見落としさえすればよい。
  • 自分は自分のプログラムを調べる能力がない、ということに気づいた最初のプログラマは、おそらくジョン・フォン・ノイマンその人である。彼の知人たちが伝えるところによれば、彼は絶えず自分がいかに下手くそなプログラマかを力説し、しょっちゅう人にプログラムを押し付けては、進んで間違いや下手なところを見つけてくれ、と頼んでいたという。
  • エゴレス方式の利点は誤りの検出だけではない、ということである。(中略)プログラムが仕様に合う(中略)所用期間の変動が小さくなる(中略)仕事がどの程度進んでいるかについての現実的な評価が得やすくなる。(中略)プログラムの適応力も高まる。(中略)プログラムを読む側の人にとっても有益だ
  • もし彼が誰かのところに助言を求めにいって、なんて馬鹿なミスをやっているのだ、などと嘲られたとすれば、彼は次回には助言を求めようとはしなくなる可能性が高い。だがもし誰かが彼のところにやってきて、プログラムを見てくれないかと頼んだとすれば、彼はそれを自分の能力に対する経緯と受け取って誇りをくすぐられ、自分の方から助言を求めるときにもあまり脅威を感じないようになるだろう。
  • グループまとめての移籍は稀なことではない。経営者たちはそこにある種の陰謀を疑いたがるものだが、そのような移籍は途方もない物質的利益に釣られてではなく、むしろ一緒に働くことによって得られる満足感を感じ続けたい、という欲求によって起こるのがふつうである。
  • チームのメンバーが自分がもらった任務は劣ったものだという感情を押し殺していた場合、それはチームの仕事に驚くほどの害を及ぼす可能性がある。エゴレス方式はそう感情を和らげる傾向を持つ。
  • グループの目標に関する真のコンセンサスを達成するには、グループ自身に目標を設定させる以上によい方法はない。
  • 目標設定に参加すること自体が各個人がチームの作業目標を真に受け入れ、その結果として生産性が高まるかどうかについての重要な決定要因になっているように見受けられる。
  • 最大の危険はマネージャーが、プログラミング関係の職位を経て昇進してきた人物であって、チームが問題をまだ見てもいないうちにビット、バイトのレベルまで決めてしまおうとする、という場合である。これほどチームの意欲を削ぎ、おれたちは「ただのコーダーさ」、と感じさせてしまうやり口はない。
  • 仕事の概要をそれがどういう意味を持つか、という視点から示す必要がある。プログラマは単に何をするかではなく、なぜそうするのかを知りたいと思うものだ。
  • プログラミング経験のない人物がプログラミングチームの管理者として任命されたとすると、その任命によるリーダーが自分は技術的なことについては能力がない、ということを積極的にまたは暗黙に認めない限り、トラブルが発生する。彼がなしうる最悪のことはチームの自分以外のメンバーとプログラミング能力を競おうとすることである。
  • 近視眼的なリーダーや自信のないリーダーは経営層をよろこばすには向こうがいってきたことを全部約束するのが最善の道だ、と感じるかもしれない。だが結局のところ、経営層が望んでいるのは果たされた約束なのだ。
  • クビを覚悟のリーダーだけが、成功への真のチャンスを握っている。
  • 人は他人の積極的強力があってこそ、ずっとすばやく、またずっとよく学ぶ
  • 大部分のプログラマは、能力を身につけていくにつれて、自分の知識を生かせないような仕事に不満を募らせはじめる。だから、プロジェクトの長期にわたる安定を願うなら、管理者はプロジェクトが一種のプログラマ加工プラントとして機能するように仕組まなければならない。
  • もしあるプログラマがかけがえのない人物だというなら、彼をできるかぎり早く追い出せ。
  • プログラム開発の進捗状況を判断するというのはきわめて主観的な仕事であり、ある1つのプログラムについてどれほどの進展があったか、という1点だけを見てもさまざまな意見が出てくる可能性がある。
  • プログラミングプロジェクトにおいて、進捗状況の評価に内在する心理学的落とし穴を回避したいと思うなら、作業することとその評価とを、なんらかの形で分離することが必要である。
  • 人々は管理者側からプロジェクトの真の状態に関する情報よりは、むしろ彼らが聞きたいと思っている答えを与えるように、と圧力を掛けられているからである。
  • どんなプログラムにも、払う注意、かける手間に関して適切なレベルというものがある。そのレベルを超えてがんばることは、そのレベルに届かないことによりもっとプロの道にもとることなのだ。
  • いまや、われわれはスケジュールが目標として存在すること自体が「割り当てられた時間」に影響することを知った。仕事が割り当てられた時間一杯まで伸びるかもしれない理由は他にも目標があって、それがスケジュールと比べたとき、どの程度重要であるか明らかにされていない、というところにあるのだ。
  • プログラミングの探偵たちは、(中略)(常人にはちょっと理解しがたいほど深く)その仕事自体に満足をおぼえる。ただしこの種の虫発見の天才は虫が見つかったあと、それを修正するのはあまり上手でない可能性がある。
  • われわれは「よいプログラマになるためには」と「よい友情を打ち建てるには」とは似ている、ということに気づくだろう。その答えはお互いに認め合うことと、個性を大切にすることである。
  • 私は自分の時間を明確な仕様を発見し、人に伝えるという方向に向けて使うのがもっとも有効だろう、という結論に達した。そして確かにそのテーマはそこに注目を向けた組織にとって大収穫をもたらすものとなった。
  • 知能は性格、作業習慣、および訓練といった要素と比べて、この問題にとっての重要性が低いように感じられる。そしてそれらの要素は知能と違って人生におけるその後の経験によって変わり得るものだ。だから問題はプログラマを選ぶことよりはむしろ育てることにある。
  • 最大の挑戦は創造的思考にあるのではなく、想像的コミュニケーションにある。つまりわれわれの考えをそれぞれ独自のスタイルを持ったほかの人々に理解可能なように表現するということが重要なのだ。
  • 金銭以外の褒章によってプログラマに動機付けを与えることも可能かもしれないのだ。仕事に納得のいく仕上げを施すための時間的余裕とか、計画段階で何ほどかの責任を分担することとかいった選択肢がある。
  • 学習における防壁はすでに内在化しているのがふつうである。だから平均的な成人は好きなようやらせておくとごく少しのことしかおぼえない。何よりもまず、学習するには自分の知らないしかし学ぶ価値のある何かが存在する、ということを承認する必要がある。プロのプログラマにとって、それを承認することは自分の地位を下げることになる。彼が真の強さを持った真のプロフェッショナルは弱みを自認したとしても何も失いはしない、ということを理解できるほどに明敏でない限りは、である。
  • プログラミング業は、どんな業種よりもっと、絶えざる学習に依存しているものだ。
  • 前進したいと願うプログラマにとって、自分が必要とする教育を公式的な教育と管理者のお慈悲にだけ求めていたのでは不十分である。
  • 学び方を学ぶ第一歩は、自分の資産と負債について知ること、言い換えれば「己を知ること」にある。
  • プログラマなら誰でも心の奥底ではプログラムは動くだけでは不満足であり、それとは別の意味で「ちゃんとして」いなければならないのだ、ということを知っている。
  • プログラミング言語において、物事を表現しやすくし、誤りを最小限にとどめるのに有効な要素のうちでも、もっとも重要なものの1つは「自然さ」である。
  • プログラミング言語が、思考過程を型にはめる性質を持っていることによる。ここでは、われわれは単純な抑制効果について述べているのではなく、プログラムやデータの構成に関する大規模な効果のことをいっている。