ちなみに

火曜日の空は僕を押しつぶした。

rbenv global 2.2.0-preview1 した話

はじめに

RubyKaigi 2日目が終了しました。去年参加出来なかったので3年ぶりのRubyKaigiです。

さて、9/18(木) に Ruby 2.2.0-preview1 がリリースされているので試してみました。 いつものように NEWS から僕の分かる部分だけを紹介します。

see also: rbenv global 2.1.0-preview2 した話 - ちなみに

インストール

すでに ruby-build に登録されているので簡単にインストールできます。

$  CONFIGURE_OPTS="--enable-bundled-libyaml" rbenv install 2.2.0-preview1
$ rbenv global 2.2.0-preview1
$ ruby -v
ruby 2.2.0preview1 (2014-09-17 trunk 47616) [x86_64-darwin13]

もしかして --enable-bundled-libyaml は不要ですか。

気になった変更点

NEWSを読んで気になったところをピックアップしました。理解できていないところは都合よく気にならなかったことになっています。

言語レベルの変更

nil/true/false が frozen になった

2.1 でシンボルが frozen になりましたが、nil/true/false も frozen になりました。

# 2.1
nil.instance_variable_set(:@a, 5)
p nil.instance_variable_get(:@a) #=> 5
p nil.frozen? #=> false

# 2.2
nil.instance_variable_set(:@a, 5) #=> can't modify frozen NilClass (RuntimeError)
p nil.frozen? #=> true

コアクラスの変更

binding#local_variables

ローカル変数の一覧が取得できるようになりました。

p binding.local_variables
#=> []
a = 1
p binding.local_variables
#=> [:a]

binding#receiver

呼び出したオブジェクト? bindingreceiver というのが何を指すのか理解出来ませんでした。 Method#receiver と同じ結果のようでした。

class A
  def hoge
    binding
  end
end

a = A.new
p a.hoge.receiver #=> #<A:0x007fb06983cef0>
p a.public_method(:hoge).receiver #=> #<A:0x007fb06983cef0>

Dir#fileno

ディレクトリのファイルディスクリプタを取得出来るようになりました。

Enumerable

#slice_after が追加

Enumerable#slice_before の逆バージョンが追加されました。 条件に一致した要素の後ろで配列を分割してチャンクを作ります。 引数としてパターンを渡した場合は === でマッチ、ブロックの場合は true を返したときに分解します。

p [0,2,4,1,2,4,5,3,1,4,2].slice_before(&:even?).to_a
#=> [[0], [2], [4, 1], [2], [4, 5, 3, 1], [4], [2]]
p [0,2,4,1,2,4,5,3,1,4,2].slice_after(&:even?).to_a
#=> [[0], [2], [4], [1, 2], [4], [5, 3, 1, 4], [2]]

min/max/min_by/max_by が取得する数を指定出来るように変更

値が大きい順に2つ取得みたいなことが出来るようになりました。

list = [5, 2, 1, 6, 9, 3]
p list.max(2) #=> [6, 9]

Float#next_float、Float#prev_float

Fixnum#succ の Float 版…?

p 1.0.next_float
#=> 1.0000000000000002
p 1.0.prev_float
#=> 0.9999999999999999

File#birthtime、File::Stat#birthtime

ファイルの作成日を取得できるようになりました。 Pathname にも追加されています。

インクリメンタルGC の導入

GC の更なる改善として、インクリメンタルGCが導入されました。 笹田さんのるびまの記事に詳しいです。

Rubyist Magazine - YARV Maniacs 【第 12 回】 インクリメンタル GC の導入

Kenel#itself

自分自身を返すメソッドが追加されました。 何がべんりなのか分からなかったのですがチケットを読んでたらなるほどという感じ。

p [1, 2, 3, 1, 2, 3].group_by(&:itself) #=> {1=>[1, 1], 2=>[2, 2], 3=>[3, 3]}
# [1,2,3,1,2,3].group_by {|i| i } が簡潔に書けるようになっている

あと ActiveSupport 4.2 に入る予定の Object#itself も分かりやすかったです。

実装 も単純明快。僕でも読めた。

Process 周り

Process#spawn などでリダイレクトするオプションを指定すると、今までは read モードで開いていたのが、write モードになるようです。どういう影響があるのか理解出来ていませんが非互換なようです。

Process#spawn などのプロセス生成系のメソッドfork よりも速い vfork を使うようになりました。

Symbol が GC の対象

今まではシンボルは生成されるとそのプロセス内で唯一の存在になってプロセスが死ぬまで残り続けました。これは用途によってはセキュリティリスクになってしまいます。

今回の変更で、シンボルであっても使われていなければ GC されるようになりました。

Matrix#first_minor、 Matrix#cofactor

行列を扱う Matrix にも2つのメソッドが追加されました。 小行列を求める #first_minor と余因子を求める #cofactor です。 大学の時にもっと代数をやっておけば良かったと後悔する毎日です。

p Matrix[[1, 2, 3],[2, 3, 1],[3, 1, 2]].first_minor(0, 0)
#=> Matrix[[3, 1], [1, 2]]
p Matrix[[1, 2, 3],[2, 3, 1],[3, 1, 2]].cofactor(0, 0)
#=> 5

Method の変更

#curry

これまでも Proc#curry を使ってカリー化を行うことが出来ましたが、メソッドでも出来るようになるみたいです。

def add(a, b)
  a + b
end

ten_adder = method(:add).curry(2).(10)
ten_adder.(5) #=> 15

#super_method

super で呼べるメソッドを Method オブジェクトとして取得出来るようになりました。

p "string".public_method(:inspect).super_method
#=> #<Method: Object(Kernel)#inspect>

非互換な変更

いくつか非互換な変更があります。 全体的に僕の理解が及ばなかったので変更が明確なGC以外は省略。

GC

GC.stat で取得出来るハッシュのキーが一部変更になっています。以下で一覧が公開されているようです。

https://docs.google.com/a/happyelements.co.jp/spreadsheets/d/11Ua4uBr6o0k-nORrZLEIIUkHJ9JRzRR0NyZfrhEEnc8/edit#gid=0

標準ライブラリの変更

Digest#HMAC なくなりました

OpenSSL::HMAC を代わりに使用してください。

Etc にいくつかのメソッドが追加されました

  • Etc.uname
  • Etc.sysconf
  • Etc.confstr
  • IO#pathconf

Find/Pathname の find メソッド

ignore_error キーワード引数を受け取れるようになった。(効果は調べていない)

Pathname#/ の追加

Pathname#+ のエイリアス

p Pathname("cute")/"nyanco"/"wanco"
#=> #<Pathname:cute/nyanco/wanco>

標準ライブラリの非互換な変更

いろいろ消えたりしていました。雑多な感じなので NEWS をご覧ください。

その他

CのAPIも Deprecated だったものが一気に消えたりしていました。

おわりに

ホテルで仕事しててつらい気持ちになったのでいつものやつをやりました。 今回は時間もなかったのであまり深く調べずに速攻分かるものだけに言及しています。 さらに、あまりお遊びをする余裕がなかったのでつまらない感じになってしまいました。 (校正していないのでタイポや間違いとかたくさんありそうです…)

今年もクリスマスは予定ないのでちゃんとします。

(明日は築地で寿司を食べつつ9時半のセッションに間に合わす予定なのですが、こんな時間なので寝坊する可能性高くて厳しい。)