まずはInstall
$ brew update $ brew upgrade ruby-build $ RUBY_CONFIGURE_OPTS="--enable-shared --with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl` --with-libyaml-dir=`brew --prefix libyaml`" \ rbenv install 2.3.0 $ rbenv global 2.3.0 $ ruby --version ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]
追加機能
Frozen String Literal プラグマ
公式ブログにはmagic commentの内容が記載されていないので補足。
# frozen_string_literal: true
のような magic comment および --enable-frozen-string-literal という引数を使用することで、デフォルトString リテラルを freeze してくれる。
irbでやるとこんな感じ。
str = 'abcde' str.gsub!('a', 'x') => "xbcde" # frozen_string_literal: true str = 'abcde' str.gsub!('a', 'x') RuntimeError: can't modify frozen String from (irb):5:in `gsub!' from (irb):5 from /Users/rochefort/.rbenv/versions/2.3.0/bin/irb:11:in `<main>'
エラー時は、"can't modify frozen String" で特定できて分かりやすいです。
$ cat -n replace.rb 1 # frozen_string_literal: true 2 def replace(str) 3 str.gsub!('a', 'x') 4 end 5 str = 'abcde' 6 replace(str) 7 $ ruby replace.rb replace.rb:3:in `gsub!': can't modify frozen String (RuntimeError) from replace.rb:3:in `replace' from replace.rb:6:in `<main>'
所感
私自身文字列リテラルにミュータブルを期待した使い方を時々します。
gsub!
, tr!
も使いますし、objectの生成が抑えれるのでloopの中で <<
を使ったりします。
どう対応するかというと、dup
使ってミュータブルにしたり、magic commentでfalseにするという対応が必要とのこと。
まぁ、頻度でいうと、ミュータブルを期待していることの方が少ないとは思いますが、
この対応を入れるのは気乗りしません。
背景としては、Ruby2.2以前では文字列リテラルを使う時に、毎回オブジェクトを生成していて
GCの対象となりパフォーマンスに影響があったようです。
また、Ruby2.1以降、String#freeze を使用すると、同一オブジェクトを使用するような最適化が入るようになりました。
freeze入れると早くなるようになったため、Rails界隈でそういったPRが沢山出てきたそうです。
確かにこれはuglyなので、今回のmagic commentの対応というのは、頷けます。
しかし、Ruby3.0では、文字列リテラルはデフォルトfrozenになるそうで(正式にどうなるかは分かりませんが)、
そうなると正直そこまで困らないにしても、ミュータルブルを期待するケースでは嬉しくないなぁとうのが実感です。
他にも、String#new 時はミュータブルにする案なども検討されているようです。
ちょっと前のRebuildでこの辺りについてお話しされていました。
詳しくは、Rebuild: 118: The Lonely Operator (Matz, a_matsuda) 00:34:08 ぐらいから。
safe navigation operator
通称lonely operator(ボッチoperator)。
active supportの try! と同じ機能。
今後は、基本ボッチを使えばok。
obj = nil obj&.foo => nil obj = false obj&.foo NoMethodError: undefined method `foo' for false:FalseClass
ちなみにactive_supportは以下。
require 'active_support' require 'active_support/core_ext' # try obj = nil obj.try(:foo) => nil obj = false obj.try(:foo) # try! obj = nil obj.try!(:foo) obj = false obj.try!(:foo)
所感
これは良いですね。
try と try! の違いは、reciverがnil以外の時に nilを返すか、NoMethodError を返すかです。
try は問題点があり、単なるmethod typo時に気づかないケースがありました。そのため、try! が推奨されていたようです。(知らんかった)
詳しくは、Rebuild: 118: The Lonely Operator (Matz, a_matsuda) 00:26:44 ぐらいから。
did_you_mean
yuki24/did_you_mean がバンドルされました。
>> mthosd NameError: undefined local variable or method `mthosd' for main:Object Did you mean? methods method
これは、便利。どう実装されているのか気になります。
他
その他、細かいところでいろいろ入っているようです。
ruby/NEWS at v2_3_0 · ruby/ruby
ご参考
・サンプルコードでわかる!Ruby 2.3の主な新機能 - Qiita
細かいところまで、実コードで解説されてます。 Hash#dig, Array#dig, Enumerable#grep_v 良さそう。