Ruby 2.3の新機能

本投稿はNithin Bekalさんの[ブログ](http://nithinbekal.com/posts/ruby-2-3-features/)で紹介されているRuby 2.3の新機能を和訳したものである。また、動作確認を兼ねて内容を一部改版している。

Ruby 2.3.0が2015年のクリスマスにリリースされる。これに向け、つい数週間前にプレビュー版が利用可能になった。

そこでRuby 2.3の新機能について幾つか紹介したいと思う。

## プレビュー版のインストール方法

### RVMの場合

```rb
$ rvm install 2.3.0-preview1
```

### rbenvの場合

```rb
$ rbenv install 2.3.0-preview1
```

## Safe navigation operator

新しい演算子`&.`が追加になった。

これはオブジェクトが`nil`ではないかどうかを判別し、演算子以降のメソッドを安全に呼ぶために利用できる。

### Ruby <= 2.2.x

```rb
if user && user.admin?
  # do something
end
```

### Ruby 2.3

```rb
if user&.admin?
  # do something
end
```

但し、気をつけるべき点が1つあり、オブジェクトが`false`の場合は後続のメソッドが実行されてしまう。そのため、`false.admin?`を実行し例外となってしまう。

## Frozen string literals

Ruby 2.2では文字列はデフォルトだとミュータブル(値を変更することが可能)である。

```rb
str = 'foobar'
str[2] = 'z'
str #=> "fozbar"
```

もしイミュータブルな文字列にしたければString#freezeを実行する必要がある。

```rb
str = 'foobar'.freeze
str[2] = 'z'
RuntimeError: can't modify frozen String
```

文字列のfreeze(immutable)化はパフォーマンスの向上にもつながる。
というのも、そうすることでRubyでは管理するオブジェクトが少なくて済むからだ。
こういった事情もあり、Ruby 3.0ではデフォルトで文字列をimmutableにしようという[計画](https://bugs.ruby-lang.org/issues/11473)がある。

その文字列のimmutable化の実現を加速するため、Ruby 2.3では文字列のimmutable化を適用するオプションが用意されている。

以下のようにファイルの先頭行に`frozen_string_literal: true`コメントを追加することで有効になる。
有効にしたら同ファイル上の全ての文字列オブジェクトは`String#freeze`を呼ばなくてもimmutableなオブジェクトとして機能するのである。

```rb
# frozen_string_literal: true

str = 'cat'
str[0] = 'b'

# frozen.rb:5:in `[]=': can't modify frozen String (RuntimeError)
#   from frozen.rb:5:in `<main>'
```

もっと詳しく知りたい方は[こちら](https://wyeworks.com/blog/2015/12/1/immutable-strings-in-ruby-2-dot-3/)の記事を読むと言いだろう。


## Array#dig and Hash#dig

次は、`Array`クラスと`Hash`クラスに追加された`dig`メソッドだ。
ネスト化された各要素に一度のメソッド呼び出しでアクセスできるAPIである。

### Arrayの場合

```rb
list = [
  [2, 3],
  [5, 7, 9],
  [ [11, 13], [17, 19] ]
]

list.dig(1, 2)    #=> 9
list.dig(2, 1, 0) #=> 17
list.dig(0, 3)    #=> nil
list.dig(4, 0)    #=> nil
```

### Hashの場合

```rb
dict = {
  a: { x: 23, y: 29 },
  b: { x: 31, z: 37 }
}

dict.dig(:a, :x) #=> 23
dict.dig(:b, :z) #=> 37
dict.dig(:b, :y) #=> nil
dict.dig(:c, :x) #=> nil
```

## “Did you mean?”

メソッド名の打ち間違い(typo)で`NoMethodError`した時に、「ひょっとしてこれですか？」って正しいメソッドを提案してくれる機能。これはRuby初心者にとっては有り難い機能では？

```rb
2.3.0-preview1 :001 > "foo bar".uppcase
NoMethodError: undefined method `uppcase' for "foo bar":String
Did you mean?  upcase
               upcase!
```




## Hash “comparison”

Ruby 2.3ではHashオブジェクト同士の比較ができるようになった。

下記の例をご覧いただくのが早いだろう。

```rb
{ x: 1, y: 2 } >= { x: 1 } #=> true
{ x: 1, y: 2 } >= { x: 2 } #=> false
{ x: 1 } >= { x: 1, y: 2 } #=> false
```

他にも比較演算子が用意されているがもっと知りたい方はこの[ブログ](http://olivierlacan.com/posts/hash-comparison-in-ruby-2-3/)を参考にすると良いだろう。


## Hash#to_proc

HashオブジェクトをProcオブジェクトに変換するメソッド`to_proc`が導入された。
Procオブジェクト化されたHashは元々のキーを使用し呼び、値を取得することができる。

```rb
h = { foo: 1, bar: 2, baz: 3}
p = h.to_proc

p.call(:foo)  #=> 1
p.call(:bar)  #=> 2
p.call(:quux) #=> nil
```

## Hash#fetch_values

`Hash#values_at`に似た`Hash#fetch_values`が導入された。
このメソッドは該当のキーが検出された場合のみ、キーに対する値の配列を返すというものだ。
値が無かった場合、`#values_at`は`nil`を返すのに対して、 `#fetch_values`は例外`KeyError`を上げる。

```rb
h = { foo: 1, bar: 2, baz: 3}
h.fetch_values(:foo, :bar) #=> [1, 2]

h.values_at(:foo, :quux)    #=> [1, nil]
h.fetch_values(:foo, :quux) #=> raise KeyError
```

## Enumerable#grep_v

`Enumerable#grep_v`メソッドは`grep`コマンドの`-v`オプションと同等の役割を担う。
引数に与えた条件にマッチしない場合に要素を返す。

```rb
list = %w(foo bar baz)

list.grep_v(/ba/)
#=> ['foo']

list.grep(/ba/)
#=> ['bar', 'baz']
```

## Numeric#positive? and #negative?

これは長らくRailsのコアにあったものだがRubyに移植されることになった。

```rb
> 1.positive?
# => true
> -1.negative?
# => true
```

## 最後に

大変お忙しい中、私の投稿を最後まで読んで頂き有難うございました😊

現在、Udemyというオンライン学習プラットフォームで[GraphQL](http://bit.ly/2JLHqYZ)や[React](http://bit.ly/2zF07J4)が学べるコースを公開しており、有り難いことに大変ご好評頂いております。

下記のリンクからだと95%オフの価格で購入できますので、もしご興味がありましたらご覧頂けると大変嬉しいです😊

* 「[GraphQL with React入門 - QueryとMutationを学びPaginationの実装にチャレンジ！](http://bit.ly/2JLHqYZ)」
* 「[フロントエンドエンジニアのためのReact・Reduxアプリケーション開発入門](http://bit.ly/2zF07J4)」

それでは今日も皆様にとってハッピーなハッキングライフを!!!😋

Dive into Hacking!!!🤩

はむ