Ruby 2.4 の変更内容 その1

Ruby 2.5 がリリースされたので、そろそろ Ruby 2.3 から 2.4 にしようかと思う今日この頃です。

この前 Ruby 2.5 の変更内容の記事を書きましたが、Ruby 2.4 についてちゃんと調べてなかったので今さらですが調べてみました。

元ネタは https://github.com/ruby/ruby/blob/v2_4_3/NEWS です。

長くなったので3つにわけてます。



条件式中での多重代入が可能

Ruby 2.3
% ruby -W0 -e 'if (a, b = 1, 2); p [a, b]; end;'
-e:1: multiple assignment in conditional
if (a, b = 1, 2); p [a, b]; end;

Ruby 2.4
% ruby -W0 -e 'if (a, b = 1, 2); p [a, b]; end;'
[1, 2]

メソッド引数で rescue 修飾子が有効

def hoge(x)
  x
end
hoge (raise rescue nil)
Ruby 2.3
% ruby a.rb
a.rb:4: syntax error, unexpected modifier_rescue, expecting ')'
hoge (raise rescue nil)
                  ^

Ruby 2.4
% ruby a.rb

なお 2.3 でも次の書き方は問題ないです。

hoge((raise rescue nil))

トップレベルで return 可能

p 123
return
Ruby 2.3
% ruby a.rb
123
a.rb:2:in `<main>': unexpected return (LocalJumpError)

Ruby 2.4
123

Refinements

Symbol#to_proc で Refinements が有効

class A
  def hoge
    123
  end
end

module X
  refine A do
    def hoge
      789
    end
  end
end

using X

# Ruby 2.3
[A.new].map do |x| x.hoge end  #=> [789]
[A.new].map(&:hoge)            #=> [123]

# Ruby 2.4
[A.new].map do |x| x.hoge end  #=> [789]
[A.new].map(&:hoge)            #=> [789]

BasicObject##__send__ で Refinements が有効

# Ruby 2.3
p A.new.hoge             #=> 789
p A.new.__send__(:hoge)  #=> 123

# Ruby 2.4
p A.new.hoge             #=> 789
p A.new.__send__(:hoge)  #=> 789

Module#refine の引数にモジュールを指定可

Ruby 2.3 ではクラスしか指定できませんでした。

module M
  def hoge
    "M#hoge"
  end
end

class C
  include M
end

module X
  refine M do
    def hoge
      "X#hoge"
    end
  end
end

c = C.new
c.hoge      #=> "M#hoge"
using X
c.hoge      #=> "X#hoge"

Module.used_modules 追加

現在のスコープで使用されているモジュールの一覧を配列で返します。

class C
end

module A
  refine C do
  end
end

module B
  refine C do
  end
end

Module.used_modules  #=> []
using A
Module.used_modules  #=> [A]
using B
Module.used_modules  #=> [B, A]

正規表現

\X がUnicodeの絵文字の結合文字にも適合

s = "👨\u{1F3FF}"  # 男と濃い肌色の結合文字
s =~ /\A\X\z/     #=> 0 (2.3 では nil)

正規表現エンジン Onigmo 6.1.1

非包含オペレータ (?~式) が追加されました。

/\A(?~abc)\z/ =~ "abc"  #=> nil

スレッドがデッドロックした時にバックトレースを出力

a = Mutex.new
b = Mutex.new

Thread.new do
  a.lock
  sleep 0.1
  b.lock
end

b.lock
sleep 0.1
a.lock
sleep

Ruby 2.3

% ruby a.rb
a.rb:12:in `lock': No live threads left. Deadlock? (fatal)
        from a.rb:12:in `<main>'

Ruby 2.4

% ruby a.rb
a.rb:12:in `lock': No live threads left. Deadlock? (fatal)
2 threads, 2 sleeps current:0x0000564d7fccdf60 main thread:0x0000564d7fccdf60
* #<Thread:0x0000564d7fd01e98 sleep_forever>
   rb_thread_t:0x0000564d7fccdf60 native:0x00007f87af8ea640 int:0
   a.rb:12:in `lock'
   a.rb:12:in `<main>'
* #<Thread:0x0000564d7fee2cf8@a.rb:4 sleep_forever>
   rb_thread_t:0x0000564d80019b80 native:0x00007f87ad967700 int:0 mutex:0x0000564d7fccdf60 cond:1
   a.rb:7:in `lock'
   a.rb:7:in `block in <main>'
        from a.rb:12:in `<main>'

TRUE, FALSE, NIL が deprecated

使用すると warning が出力されます。

Unicode 9.0.0

Unicdoe のバージョンが 8.0.0 から 9.0.0 になりました。

サポートプラットフォーム

FreeBSD 4 未満はサポート外になりました。