本投稿はNithin Bekalさんのブログで紹介されているRuby 2.3の新機能を和訳したものである。また、動作確認を兼ねて内容を一部改版している。
Ruby 2.3.0が2015年のクリスマスにリリースされる。これに向け、つい数週間前にプレビュー版が利用可能になった。
そこでRuby 2.3の新機能について幾つか紹介したいと思う。
プレビュー版のインストール方法
RVMの場合
$ rvm install 2.3.0-preview1
rbenvの場合
$ rbenv install 2.3.0-preview1
Safe navigation operator
新しい演算子&.
が追加になった。
これはオブジェクトがnil
ではないかどうかを判別し、演算子以降のメソッドを安全に呼ぶために利用できる。
Ruby <= 2.2.x
if user && user.admin?
# do something
end
Ruby 2.3
if user&.admin?
# do something
end
但し、気をつけるべき点が1つあり、オブジェクトがfalse
の場合は後続のメソッドが実行されてしまう。そのため、false.admin?
を実行し例外となってしまう。
Frozen string literals
Ruby 2.2では文字列はデフォルトだとミュータブル(値を変更することが可能)である。
str = 'foobar'
str[2] = 'z'
str #=> "fozbar"
もしイミュータブルな文字列にしたければString#freezeを実行する必要がある。
str = 'foobar'.freeze
str[2] = 'z'
RuntimeError: can't modify frozen String
文字列のfreeze(immutable)化はパフォーマンスの向上にもつながる。
というのも、そうすることでRubyでは管理するオブジェクトが少なくて済むからだ。
こういった事情もあり、Ruby 3.0ではデフォルトで文字列をimmutableにしようという計画がある。
その文字列のimmutable化の実現を加速するため、Ruby 2.3では文字列のimmutable化を適用するオプションが用意されている。
以下のようにファイルの先頭行にfrozen_string_literal: true
コメントを追加することで有効になる。
有効にしたら同ファイル上の全ての文字列オブジェクトはString#freeze
を呼ばなくてもimmutableなオブジェクトとして機能するのである。
# 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>'
もっと詳しく知りたい方はこちらの記事を読むと言いだろう。
Array#dig and Hash#dig
次は、Array
クラスとHash
クラスに追加されたdig
メソッドだ。
ネスト化された各要素に一度のメソッド呼び出しでアクセスできるAPIである。
Arrayの場合
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の場合
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初心者にとっては有り難い機能では?
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オブジェクト同士の比較ができるようになった。
下記の例をご覧いただくのが早いだろう。
{ x: 1, y: 2 } >= { x: 1 } #=> true
{ x: 1, y: 2 } >= { x: 2 } #=> false
{ x: 1 } >= { x: 1, y: 2 } #=> false
他にも比較演算子が用意されているがもっと知りたい方はこのブログを参考にすると良いだろう。
Hash#to_proc
HashオブジェクトをProcオブジェクトに変換するメソッドto_proc
が導入された。
Procオブジェクト化されたHashは元々のキーを使用し呼び、値を取得することができる。
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
を上げる。
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
オプションと同等の役割を担う。
引数に与えた条件にマッチしない場合に要素を返す。
list = %w(foo bar baz)
list.grep_v(/ba/)
#=> ['foo']
list.grep(/ba/)
#=> ['bar', 'baz']
Numeric#positive? and #negative?
これは長らくRailsのコアにあったものだがRubyに移植されることになった。
> 1.positive?
# => true
> -1.negative?
# => true
最後に
大変お忙しい中、私の投稿を最後まで読んで頂き有難うございました😊
現在、Udemyというオンライン学習プラットフォームでGraphQLやReactが学べるコースを公開しており、有り難いことに大変ご好評頂いております。
下記のリンクからだと95%オフの価格で購入できますので、もしご興味がありましたらご覧頂けると大変嬉しいです😊
- 「GraphQL with React入門 - QueryとMutationを学びPaginationの実装にチャレンジ!」
- 「フロントエンドエンジニアのためのReact・Reduxアプリケーション開発入門」
それでは今日も皆様にとってハッピーなハッキングライフを!!!😋
Dive into Hacking!!!🤩
はむ