Ruby2.3.0-preview2 の新機能を触ってみた

先日RubyKaigi2015に参加してきまして、Ruby2.3.0-preview2が出た！との事。
新機能をいち早く触ってみたのでご紹介します。

# frozen-string-literal #

ソースファイル内の全ての文字列リテラルを不変にする新しいマジックコメントとコマンドラインオプションが導入される、とのことです。

```rb
# frozen-string-literal :true
SAMPLE = 'sample'
class Sample
  def self.reverse_string
    SAMPLE.reverse!
  end
end

p Sample.reverse_string

# => RuntimeError: can't modify frozen String
```
もしくは`--enable=frozen-string-literal`というパラメータを渡すこともできます。
またデバッグ用に`--debug=frozen-string-literal`オプションを渡すとエラーが発生したオブジェクトがどこで生成されたかを知ることができるようです。


# safe navigation operator &. #
またの名をぼっちoperatorだそうです。nilのハンドリングを簡単にしてくれるものだそうです。
ex：`obj&.foo`
実例ですと以下のような感じでしょうか。

```rb
user = User.find(1)
=> #<User:0x007fa586b97700
 @attributes=
  {"id"=>1,
   "name"=>"hoge",
   "email"=>"hoge@fuga.com",
   "image"=>
    #<User::Image:0x007fa586b95a18
     @attributes=
      {"url"=>"http://hogehoge.jpg",
       "id"=>1,
       }>,
  }>

user.image&.url #=> 'http://hogehoge.jpg'

user = User.find(1)
=> #<User:0x007fa586b97700
 @attributes=
  {"id"=>1,
   "name"=>"hoge",
   "email"=>"hoge@fuga.com",
   "image"=>nil,
  }>

user.image&.url #=> nil
```

このレベルだと`user.image.try(:url)`でもいい気がしますね。

# did_you_mean #
[did_you_mean gem](https://github.com/yuki24/did_you_mean)がbundleされました。
typo多い私としては非常に助かるでございます。

```rb
sample = 'sample'
smple << '_test'

#=> NameError: undefined local variable or method `smple' for main:Object
# Did you mean?  sample
```
pry-byebugと組み合わせたエラー画面は以下
<img width="1280" alt="スクリーンショット 2015-12-15 18.56.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/87949/ae633964-411b-ab3b-de4b-db5de62890bc.png">
素敵。


# ArrayクラスとHashクラスに関するupdate #

## Array#bsearch_index ##

条件を満たす値を二分探索で検索する`Array#bsearch`のindexを返します。

```rb
list = [ 1, 3, 6, 9, 12 ]
list.bsearch_index { |x| x >= 5 } #=> 2
list.bsearch { |x| x >= 5 } #=> 6
```


## Array#dig /  Hash#dig ##
digメソッドです。ネストされたArrayやHashにアクセスできる、とのこと。

```rb
# Arrayクラスの場合
list = [[1, 2], [[3, 4], [5, 6]]]
list.dig 0 #=> [1, 2]
list.dig(0, 0) #=> 1
list.dig(1, 0, 0) #=> 3

# Hashクラスの場合
list = { a: 'b', c: { d: 'e', f: 'g' } }
list.dig :a #=> 'b'
list.dig(:c, :d) #=> 'e'

# Hashの中に配列がある場合
list = { a: 'b', c: { d: 'e', f: 'g' }, h: [[1, 2], [[3, 4], [5, 6]]] }
list.dig(:h, 0, 0) #=> 1　
```
たとえば日本の地域、県名、市名のハッシュから市名を抜き出すとか？

```rb
areas = {
  area: { id: 1, name: '関東',
    prefecture: { id: 1, name: '東京',
      city: [
        { id: 1, name: '目黒' },
        { id: 1, name: '恵比寿' },
        { id: 1, name: '渋谷' }
      ] 
    } 
  } 
}

areas.dig(:area, :prefecture, :city, 2, :name) #=> '渋谷'
```
実際は関東の下も配列で複数の県名がぶら下がる形になるでしょうし、
配列のindexをいかに取得するか？でキレイに書けるかどうか変わってきそうですね。

## Hash#fetch_values ##

Hashのvaluesを一括で取得します。

```rb
list = { a: 1, b: {c: 2, d: 3 }, e: 4, g: 5 }
list.fetch_values(:a, :e) #=> [1, 4]
list.fetch_values(:a, :b, :g) #=> [1, {:c=>2, :d=>3}, 5]
list.fetch_values(:c) #=> KeyError: key not found: :c
```
値がhash形式であっても、そのまま取得できるんですね。
合わせ技でこんなことも。

```rb
list =  { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }
list.fetch_value(:a, :c, :e).bearch_index { |x| x >= 4 } #=> 2
```

例えばこんな使い方とかいかがでしょうか。

```rb
place = Place.find(1)
=> #<Place:0x007fa586b97700
 @attributes=
  {"id"=>1,
   "name"=>"hoge",
   "images"=>
    [#<Place::Image:0x007fa586b95a18
     @attributes=
      {"url"=>"http://hogehoge.jpg",
       "id"=>1,
       }>,
     #<Place::Image:0x007fa586b95b21
     @attributes=
      {"url"=>"http://hogehuga.jpg",
       "id"=>2,
       }>,
  }>

id, name, images = user.attributes.fetch_values('id', 'name', 'images')

id #=> 1
name #=> "hoge"
images #=>[#<Place::Image:0x007fa586b95a18
#     @attributes=
#      {"url"=>"http://hogehoge.jpg",
#       "id"=>1,
#       }>,
#     #<Place::Image:0x007fa586b95b21
#     @attributes=
#      {"url"=>"http://hogehuga.jpg",
#       "id"=>2,
#       }>]
```

## Hash#<=, Hash#<, Hash#>=, Hash#> ##

Hashの包含関係を判定します。

```rb
{a: 1, b: 2} >= {a: 1} #=> true
{a: 1, b: 2} >= {a: 1, b: 2} #=> true
{a: 1, b: 2} > {a: 1, b: 2} #=> false
```

## Hash#to_proc ##
Hashをproc化します。

```rb
list = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }
list.to_proc(:a) #=> 1

# mapに渡す
[:a, :b, :c].map(&list) #=> [1, 2, 3]
```
procという便利なクラスがあったんですね。そもそもそこからして発見でした。



いかがでしたでしょうか？
新しく追加された機能とArrayとHashについての変更点をまとめてみました。
詳しくはhttps://github.com/ruby/ruby/blob/v2_3_0_preview2/NEWS を見てみて下さいね。
例年通りであれば2015/12/25にRuby2.3.0がリリースになります。良いRuby Lifeを！