Ruby2.0 Getting Started
     Ruby2.0をはじめよう!
• Ruby2.0について
• 新機能紹介
• 非互換性
• パフォーマンス


Agenda
About Ruby2.0
      Ruby2.0について




About Ruby2.0
•   2013年2月24日にリリース( Ruby20歳の誕生日! )
•   Ruby1.9との高い互換性
•   数多くの新機能
•   パフォーマンスの向上
•   2.0.0は「安定版」リリース
•   「Rubyは言語として2.0でほぼ完成」by matz



About Ruby2.0
Future
         新機能紹介




Future
•   キーワード引数
•   Enumerable#lazy
•   Module#prepend
•   シンボルリストリテラル
•   Refinments
•   その他



Future
Keyword Arguments
         キーワード引数




Keyword Arguments Future
~1.9でも実現可能
def hello(options = {})
  # デフォルト値を適用
  options = {name: "guest"}.merge(options)
  puts "Hello #{options[:name]}!!"
end

hello #=> Hello guest!!
hello(name: "taro") #=> Hello taro!!




Keyword Arguments Future
2.0ではこうなる
def hello(name: "guest")
  puts "Hello #{name}!!"
end

hello #=> Hello guest!!
hello(name: "taro") #=> Hello taro!!




Keyword Arguments Future
シンプルに書けるようになった!
# Ruby1.9
def hello(options = {})
  options = {name: "guest"}.merge(options)
  puts "Hello #{options[:name]}!!"
end

# Ruby2.0
def hello(name: "guest")
  puts "Hello #{name}!!"
end


Keyword Arguments Future
引数の存在チェックもしてくれる
def hello(name: "guest")
  puts "Hello #{name}!!"
end

hello(nama: "jiro") #=> ArgumentError: unknown keyword: nama




Keyword Arguments Future
**で残りのHashを受け取れる
def hello(name: "guest", **options)
  msg = "Hello #{name}!!"
  msg.upcase! if options[:upcase]
  puts msg
end

hello(name: "hanako") #=> Hello hanako!!
hello(name: "hanako", upcase: true) #=> HELLO HANAKO!!




Keyword Arguments Future
最後の引数がHashのメソッドは注意
def foo(somehash, option: 1)
  # do something...
end

# 引数の最後がHashの場合、キーワードだと判断される
hash_arg = {name: "guest"}
foo(hash_arg) #=> ArgumentError: unknown keyword: name
# オプションとして空のHashを指定することで回避可能
foo(hash_arg, {})



Keyword Arguments Future
積極的に使うべき!!

• オプションパラメータを受けるメソッドがシンプル
  に実装できる
• 引数の存在チェックもしてくれる
• 引数の最後にHashを受ける場合は使わない




Keyword Arguments Future
Enumerable#lazy
       遅延評価イテレータ




Enumerable#lazy Future
Enumerable#lazyって?

•   遅延評価を行うEnumeratorを返すメソッド
•   遅延評価=必要とされるまで評価(実行)しない
•   selectやmapの利用範囲が広がる
•   巨大なリストの処理が省メモリに




Enumerable#lazy Future
1~1億の奇数を5個取り出してみる
# lazy不使用:なかなか結果が返ってこない
(1..100000000).select{|num| num.odd?}.take(5)
#=> [1, 3, 5, 7, 9]

# lazy使用:すぐに結果が返ってくる
(1..100000000).lazy.select{|num| num.odd?}.take(5).force
#=> [1, 3, 5, 7, 9]




Enumerable#lazy Future
Enumerable#lazyの使い道
•   IO・Range・巨大な配列を省メモリに処理
•   無限リストでselectやmapを使う
•   Railsアプリでは使い所は少ないかも
•   続きはWEBで
    http://www.techscore.com/tech/Ruby/ruby-2.0/lazy/




Enumerable#lazy Future
Module#prepend
  モジュールによるオーバーライド




Module#prepend Future
Module#prependって?
• Module#includeの親戚
• includeは自クラスと親クラスの間にモジュールを
  挿入
• prependは自クラスの手前にモジュールを追加
• 対象クラスのメソッドをオーバーライド可能に




Module#prepend Future
prependとincludeの比較 - 1
module IM
  def hoge; puts "IM#hoge"; end
end
module PM
  def hoge; puts "PM#hoge"; super; end
end
class C
  include IM
  prepend PM
  def hoge; puts " C#hoge"; super; end
end

Module#prepend Future
prependとincludeの比較 - 2

# ancestorsで継承階層を表示する
C.ancestors #=> [PM, C, IM, Object, Kernel, BasicObject]

obj = C.new
obj.hoge
# PM#hoge
# C#hoge
# IM#hoge



Module#prepend Future
Module#prependの使い道

• 構造化された再利用可能なモンキーパッチ
• alias_method_chain(ActiveSupport)の撲滅
• RailsやActiveRecordなど、既存のライブラリを拡
  張するライブラリを制作する時に便利!




Module#prepend Future
Symbol list literal
        シンボルリストリテラル




Symbol list literal Future
%i %I でシンボルの配列に。便利!!
# 普通に配列リテラルで書く
[:hoge, :fuga, :piyo]           #=>[:hoge, :fuga, :piyo]

# %wしてmapする
%w(hoge fuga piyo).map(&:intern) #=>[:hoge, :fuga, :piyo]

# シンボルリストリテラル - %i (式展開なし)
%i(hoge fuga piyo)   #=>[:hoge, :fuga, :piyo]

# シンボルリストリテラル - %I (式展開あり)
%I(a#{1+1} a#{1+2})  #=>[:a2, :a3]

Symbol list literal Future
Refinements
      局所的なメソッド再定義




Refinements Future
Refinementsって?

• 局所的に特定のクラスのメソッドを変更する仕組
• Ruby2.0の目玉機能になる筈だった
• 例)ActiveRecord+Refinments
# gem activerecord-refinements
# 以下はUser.where(name: "matz")と同じ
User.where{:name == "matz"}



Refinements Future
しかし…
• 残念ながら大幅に機能削減された挙句、
  experimental(実験的)機能になってしまった
• 本来の想定どおりに実装されるとDSLの可能性
  が大きく広がる
• 2013年クリスマス頃に予定されているRuby2.1に
  大いに期待!!



Refinements Future
Others
          その他の新機能




Others Future
• デフォルトの文字コードがUTF-8に
  (マジックコメントが不要になる)
• __dir__メソッド
  (実行中ファイルのディレクトリパス)
• to_hメソッド( Hashへの型変換)
• Enumerable#size(遅延サイズ評価)
• 正規表現エンジンの変更(鬼車 → 鬼雲)
• TracePointやDtraceによるデバッグ機能の強化

Others Future
Incompatibility
         非互換性




Incompatibility
1.9 ~ 2.0の非互換性
• iconvの削除(Ruby1.9で既に非推奨)
• IO#lines, #chars, #codepoints, #bytesが
  Enumeratorではなく配列を返すようになった
• Object#inspect が#to_s を呼び出さなくなった
• デフォルトのエンコーディングがUTF-8に
• ABI互換性がなくなった
  (1.9の.soや.bundleを共用してはいけない)


Incompatibility
Performance
      パフォーマンス




Performance
最適化によるパフォーマンス向上

•   bitmap marking による GC 最適化
•   メソッドディスパッチなどの VM 最適化
•   浮動小数演算の最適化
•   Kernel#require の最適化




Performance
ベンチマーク1 - 浮動小数点演算
require 'benchmark'
puts RUBY_VERSION
puts Benchmark::CAPTION
puts Benchmark.measure {100000000.times{|i| 1.0 * i}}

            user     system      total        real
1.8.7 | 2.040000   0.000000   2.040000 ( 2.086681)
1.9.3 | 1.120000   0.000000   1.120000 ( 1.161166)
2.0.0 | 0.720000   0.000000   0.720000 ( 0.724945)


Performance
ベンチマーク2 – Rails起動速度

time RAILS_ENV=production rails runner ""


            user     system      real
1.9.3 | 0m4.104s   0m0.356s   0m4.620s
2.0.0 | 0m2.154s   0m0.365s   0m2.594s




Performance
Conclusion
         まとめ




Conclusion
Ruby2.0の魅力
• 魅力的な新機能
 • キーワード引数・lazy・prependなど
• 1.9との高い互換性
 • 殆どのコードが変更なしで動作する
• パフォーマンスの向上
 • 処理速度の向上
 • Railsの起動速度大幅に向上


Conclusion

Ruby2.0 Getting Started