10/22に2.7.0-preview2がリリースされました🎉。
機能の多くは週刊Railsウォッチでも報じてきましたが、改めて覗いてみました。「Experimental」と銘打たれた機能が割と目に付きます。誤りがありましたら@hachi8833までお知らせください🙇。
Compaction GC
GC.compact
でヒープを明示的に圧縮できます。
irb(main):006:0> GC.compact
=> {:considered=>{:T_NONE=>5736, :T_OBJECT=>258, :T_CLASS=>197, :T_MODULE=>23, :T_FLOAT=>0, :T_STRING=>5605, :T_REGEXP=>131, :T_ARRAY=>760, :T_HASH=>61, :T_STRUCT=>13, :T_BIGNUM=>0, :T_FILE=>0, :T_DATA=>177, :T_MATCH=>0, :T_COMPLEX=>0, :T_RATIONAL=>0, 16=>0, :T_NIL=>0, :T_TRUE=>0, :T_FALSE=>0, :T_SYMBOL=>8, :T_FIXNUM=>0, :T_UNDEF=>0, 23=>0, 24=>0, 25=>0, :T_IMEMO=>3979, :T_NODE=>0, :T_ICLASS=>30, :T_ZOMBIE=>0, :T_MOVED=>0}, :moved=>{:T_NONE=>0, :T_OBJECT=>258, :T_CLASS=>197, :T_MODULE=>23, :T_FLOAT=>0, :T_STRING=>5605, :T_REGEXP=>131, :T_ARRAY=>760, :T_HASH=>61, :T_STRUCT=>13, :T_BIGNUM=>0, :T_FILE=>0, :T_DATA=>177, :T_MATCH=>0, :T_COMPLEX=>0, :T_RATIONAL=>0, 16=>0, :T_NIL=>0, :T_TRUE=>0, :T_FALSE=>0, :T_SYMBOL=>0, :T_FIXNUM=>0, :T_UNDEF=>0, 23=>0, 24=>0, 25=>0, :T_IMEMO=>3979, :T_NODE=>0, :T_ICLASS=>30, :T_ZOMBIE=>0, :T_MOVED=>0}}
GC.compact
は以下を実行します。
- フルGC
- オブジェクトを移動
- 参照更新
- フルGC
パターンマッチング(Experimental)
case
構文でin
を使えるようになりました。関数型言語で広く用いられている手法です。現在はwarningが表示されます。
case {a: 0, b: 1}
in {a: 0, x: 1}
:unreachable
in {a: 0, b: var}
p var #=> 1
end
# warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!
REPL(irb)の改良
- Feature #14683: IRB with Ripper - Ruby master - Ruby Issue Tracking System
- Feature #14787: Show documents when completion - Ruby master - Ruby Issue Tracking System
- Feature #14918: Use Reline for fallback of ext/readline - Ruby master - Ruby Issue Tracking System
これも既に有名ですね。色付けやオートインデント、Tabキー2度押しでAPIドキュメント表示、履歴をブロック単位で遡る機能などが追加されました。irbを終了しても履歴が保存されるようになったのがかなりありがたいです😂。
positional引数とキーワード引数の分離
Ruby 3.0でのbreaking changeに備え、Ruby 2.7で各種warningを表示します。まだ自分の中で未消化なので別記事にしようと思います🙇。
追記(2019/11/18)以下の翻訳記事を出しました。
パフォーマンス改善
- JITの改善(Experimental)
- 以下の結果はfrozen stringになる
# シンボルのto_s
:symbol.to_s.frozen? #=> true
# Module.name
module Bar ;end
Bar.name.frozen? #=> true
# trueやfalseのto_s
true.to_s.frozen? #=> true
false.to_s.frozen? #=> true
CGI.escapeHTML
のパフォーマンスを向上
その他追加された機能追加
メソッド参照演算子.:
の追加(Experimental)
- Feature #12125: Proposal: Shorthand operator for Object#method - Ruby master - Ruby Issue Tracking System
- Feature #13581: Syntax sugar for method reference - CommonRuby - Ruby Issue Tracking System
#method(:メソッド名)
と同等です。メソッドを呼び出すのではなく、Method
オブジェクトを返します。
[1,2,3].map do |x| Math.method(:sqrt) end
# 上と下は同等
[1,2,3].map do |x| Math.:sqrt end
#=> [#<Method: Math.sqrt>, #<Method: Math.sqrt>, #<Method: Math.sqrt>]
これを用いて、ブロックとmethod
なしで以下のように短く書けます。
[1,2,3].map(&Math.:sqrt)
#=> [1.0, 1.4142135623730951, 1.7320508075688772]
warningは表示されません。
追記(2019/11/18)その後メソッド参照演算子はひとまず取り消しになりました。
参考: Revert "Method reference operator" · ruby/ruby@fb6a489
参考: Feature #16275: Revert `.:` syntax - Ruby master - Ruby Issue Tracking System
numbered parameterの導入(Experimental)
デフォルトのブロックパラメータをショートハンドで表せます。表記法について議論の末、_1
や_2
といった表記に落ち着いたようです。
[1, 2, 10].map do |i| i.to_s(16) end
# 上と下は同等
[1, 2, 10].map do _1.to_s(16) end
#=> ["1", "2", "a"]
warningは表示されません。
range ..
の開始値の省略記法(Experimental)
Ruby 2.6で..
の終了値の省略記法が導入されたのに続き、開始値も省略可能になりました。さすがに開始値と終了値を両方省略すると構文エラーになりました。
ary = %w(1, 2, 3, 4)
ary[..3] # ary[0..3]と同等
#=> ["1,", "2,", "3,", "4"]
warningは表示されません。
Enumerable#tally
の追加
要素ごとの個数をハッシュで得られます。当初は#count_by
という名前でした。
["a", "b", "c", "b"].tally
#=> {"a"=>1, "b"=>2, "c"=>1}
tally: (競技の)得点
レシーバーにself
を指定してprivateメソッドを呼べるようになった
- Feature #11297: Allow private method of self to be called - Ruby master - Ruby Issue Tracking System
- Feature #16123: Allow calling a private method with `self.` - Ruby master - Ruby Issue Tracking System
インスタンスメソッドからprivateメソッドを呼び出すときにレシーバーにself
を指定してもエラーにならなくなりました。
# 従来
class Foo
def foo
self.baz # レシーバーは指定できないのでエラー
end
def bar
baz # 呼べる
end
private
def baz
42
end
end
Foo.new.foo
#=> NoMethodError (private method `bar' called for #<Foo:0x000055b4b7980258>)
Foo.new.bar
#=> 42
# 2.7
class Foo
def foo
self.baz # selfならレシーバーとして指定できるので呼べる
end
def bar
baz # 呼べる
end
private
def baz
42
end
end
Foo.new.foo #=> 42
Foo.new.bar #=> 42
従来のprivateメソッドは「関数形式でしか呼び出せない」つまり「呼び出しでレシーバーを指定できない」という概念でしたが、「呼び出しでself
以外のレシーバーを指定できない」みたいに変わることになりそうですね。
参考: クラス/メソッドの定義 (Ruby 2.6.0)
参考: [Ruby] privateメソッドの本質とそれを理解するメリット - Qiita
Enumerator::Lazy#eager
を追加
Enumerator::Lazy
からEnumerator
を生成します。
a = %w(foo bar baz)
e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }
e.class #=> Enumerator::Lazy
e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
e.class #=> Enumerator
メソッドに渡されたブロックを(ブロックなしの)Proc.new
やproc
で受けるとwarningを表示
- commit: proc.c: proc without block · ruby/ruby@9f1fb0a
- 参考: "warning: Capturing the given block using Proc.new is deprecated" · Issue #2058 · aws/aws-sdk-ruby (Rubyのissueではありませんが)
これができていたこと自体初めて知りました😳。
def foo
proc.call # またはProc.new.call
end
foo { puts "Hello" }
#=> warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
#=> Hello
メッセージにあるようにブロック引数(&block
など)か、yield
で従来どおりに受けられます。
# 従来どおり
def foo(&block)
block.call
end
foo { puts "Hello" } #=> Hello
def foo
yield
end
foo { puts "Hello" } #=> Hello
メソッドに渡されたブロックを(ブロックなしの)lambda
で受けるとArgumentErrorを表示
def foo
lambda.call
end
foo { puts "Hello" }
#=> ArgumentError (tried to create Proc object without a block)
従来は以下のwarningが表示されていましたが、2.7で完全に禁止になります。
# warning: tried to create Proc object without a block
#=> Hello
Unicode v12の絵文字対応
Unicode version 12で追加された大量の絵文字に対応しました。Ruby 2.6系も対象になるとあります。
参考: Emoji List, v12.0 -- 1,719個あります。
令和対応
- Feature #15195: Deal with new Japanese era - Ruby master - Ruby Issue Tracking System
- Feature #15742: Add Date#jisx0301 support new Japanese era - Ruby master - Ruby Issue Tracking System
なお#15195は2.6.3以降にも導入済みです。
"\u32FF"
#=> "㋿"
Date.new(2019, 5, 1).jisx0301
#=> "R01.05.01"
コンパイラをC99必須に、C90サポートを廃止
参考: C99 - Ruby master - Ruby Issue Tracking System
おたより発掘
助かるまとめ記事👏
Ruby 2.7.0-preview2がリリース https://t.co/jJB7oUmkmk
— Masafumi Koba 🇺🇦 (@ybiquitous) October 23, 2019