3つの主要な追加feature
リリースブログにて下記3つが取り上げられています。
https://www.ruby-lang.org/en/news/2015/11/11/ruby-2-3-0-preview1-released
1. Frozen String Literal Pragma
Stringリテラルを標準でfreezeさせる Frozen String Literal Pragma の導入。指定には下記の2パターン。
コマンドラインオプションに --enable-frozen-string-literal
をつける
ruby --enable-frozen-string-literal sample.rb
マジックコメント # frozen_string_literal: true
をつける
# frozen_string_literal: true
"abc".reverse!
# => RuntimeError: can't modify frozen String
2. Safe navigation operator
nilのハンドルを便利にする Safe navigation operator が追加。Railsのtry!のようなもの。
obj = nil
obj&.foo
# => nil
obj = "sample"
obj&.foo
# => NoMethodError
3. did_you_mean gem
NameError
や NoMethodError
が発生した時にメソッドをサジェストする did you mean gemが組み込まれた。
@full_name = "Sample Taro"
first_name, last_name = full_name.split(" ")
# => NameError: undefined local variable or method `full_name' for main:Object
#
# Did you mean? @full_name
#
その他のアップデート
追加されたメソッド系を中心に取り上げます。
https://github.com/ruby/ruby/blob/v2_3_0_preview1/NEWS
Array#bsearch_index #10730
Array#bsearch(2分探索)の結果のindex番号を返す
[0, 4, 7].bsearch_index {|x| x >= 4 } # => 1
[0, 4, 7].bsearch_index {|x| x >= 6 } # => 2
Enumerable#grep_v #11049
Enumerable#grepの逆(マッチしない)の要素を集める
%w(aaa bbb ccc).grep(/b/) #=> ["bbb"]
%w(aaa bbb ccc).grep_v(/b/) #=> ["aaa", "ccc"]
grep -v
コマンド欲しいよねって事から
Enumerable#chunk_while #10769
ブロックで指定した条件ごとに部分配列に分ける
# 隣り合う偶数同士、奇数同士の部分配列ごとに分ける。
[7, 5, 9, 2, 0, 7, 9, 4, 2, 0].chunk_while{|i, j| i.even? == j.even?}.to_a
# => [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
Hash#fetch_values #10017
Hashから複数のvaluesをfetchする
{ one: 1, two: 2, three: 3 }.fetch_values(:two, :three) #=> [2, 3]
ログ見るとメソッド名について投票あったり議論されてて面白い。
Hash#dig #11643
HashやArrayを深堀りするのにnilをうまく扱える
hash = { user: { avatar: { path: "sample.png" } } }
hash[:user][:avatar][:path]
#=> "sample.png"
hash.dig(:user, :avatar, :path)
#=> "sample.png"
hash[:user][:photo][:photo]
#=> NoMethodError
hash.dig(:user, :photo, :path)
#=> nil
Arrayにも実装
array = [1, [2, [3]]]
array[1][1][0]
#=> 3
array.dig(1, 1, 0)
#=> 3
array[1][2][3]
#=> NoMethodError
array.dig(1, 2, 3)
#=> nil
Hash#<=, Hash#<, Hash#>=, Hash#> #10984
Hashの包含関係を判定する
{ a: 1, b: 2 } <= { a: 1, b: 2 } # => true
{ a: 1, b: 2, c: 3 } <= { a: 1, b: 2 } # => false
{ a: 1, b: 2 } < { a: 1, b: 2 } # => false
{ a: 1, b: 2 } < { a: 1, b: 2, c: 3 } # => true
Hash#to_proc #11653
HashをProc化してMapに渡したりできるように
my_hash = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }
my_hash.to_proc.call(:a)
# => 1
[:e, :a, :b, :f, :c, :d].map(&my_hash)
# => [5, 1, 2, 6, 3, 4]
Procは[]でcallできるのにHashがProcにmappableじゃないよねとのことから。
Module#deprecate_constant #11398
Deprecatedなconstantに使う
TimeoutError = Timeout::Error
class Object
deprecate_constant :TimeoutError
end
NameError#receiver #10881
NameErrorのレシーバを取得する
receiver = "receiver"
exception = receiver.doesnt_exist rescue $!
exception.receiver == receiver # => true
Numeric#positive? Numeric#negative? #11151
数値のPositive/Negativeを判定する
1.positive? # => true
1.negative? # => false
0.positive? # => false
[1, -1, 2].select(&:positive?) # => [1, 2]