ruby 2.0.0-rc1が出たので、普段使いのRubyを2.0にしてみました。
インストール
($ brew install openssl readline) $ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline` --enable-bundled-libyaml" rbenv install 2.0.0-rc1 Downloading ruby-2.0.0-rc1.tar.gz... -> http://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-rc1.tar.gz Installing ruby-2.0.0-rc1... Installed ruby-2.0.0-rc1 to /Users/tomohiro/.rbenv/versions/2.0.0-rc1 $ rbenv global 2.0.0-rc1
(01/24修正) configureに--enable-bundled-libyamlオプションを追加/brew install libyaml削除)
ReadlineとOpenSSLはHomeBrewで入れたものを使うように指定しています。
余談だけど、いつからかHomeBrewがビールの絵文字出すようになっててかわいい。
気になった変更
以下を読んで気になったところをピックアップしました。
キーワード引数
本物のキーワード引数が実装されたので、Hashを使わなくてもよくなった。
def config(key, default: true, force: false, **options) [key, default, force, **options] end p config #=> wrong number of arguments (0 for 1) (ArgumentError) p config(:a) #=> [:a, true, false, {}] p config(:b, force: true) #=> [:b, true, true, {}] p config(:c, default: false) #=> [:c, false, false, {}] p config(:d, new: true) #=> [:d, true, false, {:new=>true}] p config(:e, default: false, time_out: true) #=> [:e, false, false, {:time_out=>true}]
**
がきもいですね。
Module#refine と main.using
Module
- added Module#refine, which extends a class or module locally. [experimental]
toplevel
- added method:
- added main.using, which imports refinements into the current file or eval string. [experimental]
紆余曲折の結果 Refinements がExperimentalなフィーチャとして入ることになったようです。
モンキーパッチすると広範囲に影響が及んでしまってつらいときに、影響を特定のスコープに閉じ込めるために使えます。
ただし、今回は実験的な追加であるために、using
したファイルのスコープに限られ、モジュールやクラスのスコープに閉じ込めることができません。
本格的にはModule#using
みたいなのが実装されてからでしょうか。
あと、refine
するとwarning: Refinements are experimental, and the behavior may change in future versions of Ruby!
みたな警告がでます。
module Catable refine String do def nyan "#{self}にゃん!" end end end puts 'こんにちは'.nyan #=> undefined method error using Catable puts 'こんにちは'.nyan #=> こんにちはにゃん!
Module#prepend
- Module
- added method:
- added Module#prepend which is similar to Module#include, however a method in the prepended module overrides the corresponding method in the prepending module.
ふつうはモジュールをincludeしても、同名のメソッドがinclude先のクラスなどで定義されていたらそちらが優先される。
module Catable def greet puts 'にゃん' end end class Japanese include Catable def greet puts 'こんにちは' end end Japanese.new.greet #=> こんにちは
追加されたModule#prepend
を使うと、モジュールで定義したメソッドを優先させることができる。
class Japanese prepend Catable def greet puts 'こんにちは' end end Japanese.new.greet #=> にゃん
もちろんModule#prepended
とModule#prepend_features
も追加されているので、includeと同じように使えます。
%iの追加
- Added %i and %I for symbol list creation (similar to %w and %W).
%w
のようにSymbolのリストが作れます。べんりすぎる。大文字のIだと式展開とバッククォートが有効になります。
p %i[ a b c d e f] #=> [:a, :b, :c, :d, :e, :f]
デフォルトのエンコーディングがUTF-8に
- Default source encoding is changed to UTF-8. (was US-ASCII)
互換性を気にしなくて良い場合は、マジックコメントを書かなくてもよくなったということ。地味だけどうれしい。
Enumerable#Lazy
- Enumerable
- added method:
- added Enumerable#lazy method for lazy enumeration.
Enumeratorオブジェクト(正確にはEnumerableEnumerator::Lazy)の評価を実際に値が必要になるまで遅延しくれる。(たぶんAR::Relationみたいなの)
各所で語られているので省略。
- http://route477.net/files/matrk03/
- http://www.slideshare.net/cuzic/enumerable-lazy
- Ruby 2.0 メモ: Lazy と LINQ とループ融合
- see also: https://www.google.co.jp/search?q=Enumerable%23lazy)
Kernel#Hash
- Kernel
- added method:
- added Kernel#Hash conversion method like Array() or Float().
Kernel#Hash
はKernel#Array
などのように、引数をto_hash
を使ってHashにしようとしてくれます。
何がべんりかと言うと、引数がnil
なのかHashなのか分からないときに、とにかく突っ込めばHashにしてくれるところです。
p Hash(a: 1) #=> {:a => 1} p Hash(nil) #=> {} p Hash([]) #=> {}
ただし、この用途では、NilClass#to_h
とHash#to_h
も追加されているので、以下のようにすることもできます。
p nil.to_h #=> {} p {a: 1}.to_h #=> {:a => 1}
ちなみにKernel#Array
は以下のように使います。べんり
p Array(1) #=> [1] p Array([1]) #=> [1]
Kernel#__dir__
- Kernel
- added method:
- added Kernel#dir which returns a current dirname.
実行中のファイルが配置されているディレクトリが取れる。
File.dirname(__FILE__)
の代りに、
__dir__
と書ける。
Module#const_get の拡張
- Module
- extended method:
- Module#const_get accepts a qualified constant string, e.g. Object.const_get("Foo::Bar::Baz")
ネストした書き方が出きるようになったみたいです。
Struct#to_h (OpenStruct#to_h)
- Struct
- added method:
- added Struct#to_h returning values with keys corresponding to the instance variable names.
Struct
をHash
に変換したいときにto_h
を自前で実装しなくてよくなったようです。
あとOpenStruct
にもいくつかメソッドが追加されて地味にべんりになってました。
Array#bsearch
- Array
- added method:
- added Array#bsearch for binary search.
バイナリサーチができる。
1000000個の配列から存在しない値を探してみたらEnumerable#find
と比べて恐しく速かった。
require 'benchmark' INFINITE = 1/0.0 a = 1000000.times.map { rand(100000000) }.sort Benchmark.bmbm do |x| x.report { a.find {|i| i > INFINITE } } x.report { a.bsearch {|i| i > INFINITE }} end Rehearsal ------------------------------------ 0.110000 0.000000 0.110000 ( 0.106729) 0.000000 0.000000 0.000000 ( 0.000009) --------------------------- total: 0.110000sec user system total real 0.110000 0.000000 0.110000 ( 0.106397) 0.000000 0.000000 0.000000 ( 0.000007)
TracePoint
- TracePoint
- new class. This class is replacement of set_trace_func. Easy to use and efficient implementation.
Kernel.set_trace_func
の代りに以下のように書けるようになりました。べんりですね。
module DefaultMethods def hoge p 'hoge' end end trace = TracePoint.new(:class) {|tp| tp.self.__send__(:include, DefaultMethods) } trace.enable do class Hoge end end class Piyo end Hoge.new.hoge #=> "hoge" Piyo.new.hoge #=> undefined method `hoge' for #<Piyo:0x007ff394866228> (NoMethodError)
RubyGems
- RubyGems RubyGems 2.0.0 features the following improvements:
gem search
now defaults to --remote and is anchored like gem list.- Added --document to replace --rdoc and --ri. Use --no-document to disable documentation, --document=rdoc to only generate rdoc.
- Only ri-format documentation is generated by default.
いまさら感ありますが、gem search
のときにデフォルトで--remote
が付くようになりました。
また--no-ri --no-rdoc
も--no-document
で済むようになったようです。
ついでにRDocがデフォルトでは生成されなくなったので、ちょっと速くなってます。
Syckの削除
psychに統一されました。syckを使っている場合は注意が必要。Railsアプリの移行ではまるところありそう。
また、psychがlibyamlを使っているので、インストールしておく必要があるようです。
HomeBrewならさくっと入ります。
(01/24追記)
psychにlibyamlがバンドルされているので、configureのオプションで--enable-bundled-libyaml
を渡してやると、優先的にそちらを使うようになります。
ruby-buildでインストールする場合は以下の方法でオプションを渡せます。
CONFIGURE_OPTS="--enable-bundled-libyaml" rbenv install 2.0.0-rc1
まとめ
2.0のリリースは2月24日(日/Ruby 20th anniversary!)です。移行しない手はないので、少なくとも普段使いは2.0にしましょう。
追記
@znz さんからつっこみをいただきました。ありがとうございます。タイポは修正済です。
@tomohi_ro マジックコード→マジックコメント?Layze→Lazy?dir→__dir__?(複数)libyaml はバンドルされてるから configure で --enable-bundled-libyaml がおすすめらしいです。
— Kazuhiro NISHIYAMA (@znz) January 19, 2013
追記2
@yhara さんよりコメントでつっこみをいただきました。ありがとうございます。
正確にはEnumerable::Lazy 残念、Enumerator::Lazyだ (2.0の紹介記事書く人の50%くらいはこの間違いしそうですね)
そもそもEnumerableオブジェクトって何って話ですね。
Enumeratorオブジェクト(正確にはEnumerator::Lazy)
が正しいですね。
追記3
@kakutani さんのTweetに対して、Jeremy Kemper(!!!) さんよりフィードバックいただきました。
@znzさんのフィードバックと同様で、libyaml は不要だそうです、configureのオプションに--enable-bundled-libyaml
を加えることでpsychにバンドルされたlibyamlが優先的に使うようになります。
(これっぽい: http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=37977&view=revision via: http://d.hatena.ne.jp/nagachika/20121129/ruby_trunk_changes_37948_38001 )
@tomohi_ro ありがたいフィードバック(ぼく試せてないですごめんなさい) RT @bitsweat: @kakutani 2.0.0-rc1 bundles libyaml, so `brew install libyaml` is not required :)
— Kakutani Shintaroさん (@kakutani) 1月 23, 2013
追記4
@bitsweat さんがHomeBrewなどでインストールしたOpenSSLを優先的に使ってビルドするruby-buildのパッチを書いてくださったようです。これが入ると--with-openssl-dir=
brew --prefix openssl`と書かなくて良くなります。LifeChanging。
https://github.com/sstephenson/ruby-build/pull/273
追記5
libyamlの件がNEWSとChangeLogに追記されました。@sora_h さん++
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=38929