Ruby2.0 Getting Started Ruby2.0をはじめよう!
Agenda
• Ruby2.0について
•新機能紹介
•非互換性
•パフォーマンス
About Ruby2.0
About Ruby2.0 Ruby2.0について
About Ruby2.0
• 2013年2月24日にリリース( Ruby20歳の誕生日! )
• Ruby1.9との高い互換性
• 数多くの新機能
• パフォーマンスの向上
• 2.0.0は「安定版」リリース
• 「Rubyは言語として2.0でほぼ完成」by matz
Future
Future 新機能紹介
Future
• キーワード引数
• Enumerable#lazy
• Module#prepend
• シンボルリストリテラル
• Refinments
• その他
Keyword Arguments Future
Keyword Arguments キーワード引数
Keyword Arguments Future
def hello(options = {})
# デフォルト値を適用
options = {name: "guest"}.merge(options)
puts "Hello #{options[:name]}!!"
end
hello #=> Hello guest!!
hello(name: "taro") #=> Hello taro!!
~1.9でも実現可能
Keyword Arguments Future
def hello(name: "guest")
puts "Hello #{name}!!"
end
hello #=> Hello guest!!
hello(name: "taro") #=> Hello taro!!
2.0ではこうなる
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
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!!
**で残りのHashを受け取れる
Keyword Arguments Future
def foo(somehash, option: 1)
# do something...
end
# 引数の最後がHashの場合、キーワードだと判断される
hash_arg = {name: "guest"}
foo(hash_arg) #=> ArgumentError: unknown keyword: name
# オプションとして空のHashを指定することで回避可能
foo(hash_arg, {})
最後の引数がHashのメソッドは注意
Keyword Arguments Future
• オプションパラメータを受けるメソッドがシンプルに実装できる
• 引数の存在チェックもしてくれる
• 引数の最後にHashを受ける場合は使わない
積極的に使うべき!!
Enumerable#lazy Future
Enumerable#lazy 遅延評価イテレータ
Enumerable#lazy Future
• 遅延評価を行うEnumeratorを返すメソッド
• 遅延評価=必要とされるまで評価(実行)しない
• selectやmapの利用範囲が広がる
• 巨大なリストの処理が省メモリに
Enumerable#lazyって?
Enumerable#lazy Future
# 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]
1~1億の奇数を5個取り出してみる
Enumerable#lazy Future
• IO・Range・巨大な配列を省メモリに処理
• 無限リストでselectやmapを使う
• Railsアプリでは使い所は少ないかも
• 続きはWEBで
http://www.techscore.com/tech/Ruby/ruby-2.0/lazy/
Enumerable#lazyの使い道
Module#prepend Future
Module#prepend モジュールによるオーバーライド
Module#prepend Future
• Module#includeの親戚
• includeは自クラスと親クラスの間にモジュールを挿入
• prependは自クラスの手前にモジュールを追加
• 対象クラスのメソッドをオーバーライド可能に
Module#prependって?
Module#prepend Future
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
prependとincludeの比較 - 1
Module#prepend Future
# ancestorsで継承階層を表示する
C.ancestors #=> [PM, C, IM, Object, Kernel, BasicObject]
obj = C.new
obj.hoge
# PM#hoge
# C#hoge
# IM#hoge
prependとincludeの比較 - 2
Module#prepend Future
• 構造化された再利用可能なモンキーパッチ
• alias_method_chain(ActiveSupport)の撲滅
• RailsやActiveRecordなど、既存のライブラリを拡張するライブラリを制作する時に便利!
Module#prependの使い道
Symbol list literal Future
Symbol list literal シンボルリストリテラル
Symbol list literal Future
# 普通に配列リテラルで書く
[: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]
%i %I でシンボルの配列に。便利!!
Refinements Future
Refinements 局所的なメソッド再定義
Refinements Future
• 局所的に特定のクラスのメソッドを変更する仕組
• Ruby2.0の目玉機能になる筈だった
• 例)ActiveRecord+Refinments
Refinementsって?
# gem activerecord-refinements
# 以下はUser.where(name: "matz")と同じ
User.where{:name == "matz"}
Refinements Future
• 残念ながら大幅に機能削減された挙句、
experimental(実験的)機能になってしまった
• 本来の想定どおりに実装されるとDSLの可能性が大きく広がる
• 2013年クリスマス頃に予定されているRuby2.1に大いに期待!!
しかし…
Others Future
Others その他の新機能
Others Future
• デフォルトの文字コードがUTF-8に
(マジックコメントが不要になる)
• __dir__メソッド
(実行中ファイルのディレクトリパス)
• to_hメソッド( Hashへの型変換)
• Enumerable#size(遅延サイズ評価)
• 正規表現エンジンの変更(鬼車 → 鬼雲)
• TracePointやDtraceによるデバッグ機能の強化
Incompatibility
Incompatibility 非互換性
Incompatibility
• iconvの削除(Ruby1.9で既に非推奨)
• IO#lines, #chars, #codepoints, #bytesがEnumeratorではなく配列を返すようになった
• Object#inspect が#to_s を呼び出さなくなった
• デフォルトのエンコーディングがUTF-8に
• ABI互換性がなくなった
(1.9の.soや.bundleを共用してはいけない)
1.9 ~ 2.0の非互換性
Performance
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
Conclusion
Conclusion まとめ
Conclusion
• 魅力的な新機能
• キーワード引数・lazy・prependなど
• 1.9との高い互換性
• 殆どのコードが変更なしで動作する
• パフォーマンスの向上
• 処理速度の向上
• Railsの起動速度大幅に向上
Ruby2.0の魅力