2020/11/14 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
Pattern matching is no longer experimental
- bugs.ruby ではなくて commit
- パターンマッチが experimental ではなくなった
- 右代入は experimental になるので注意
# no warning case { name: "homu", age: 14 } in { name:, age: } end # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! { name: "homu", age: 14 } => { name:, age: }
[Feature #17176] GC.auto_compact / GC.auto_compact=(flag)
GC.auto_compact=GC.auto_compactを追加する提案GC.auto_compact = trueにすることで GC 中に自動でGC.compactを呼び出す- よくわからないので詳細はチケットとか読んでね
[Feature #17294] Feature: Allow method chaining with Pathname#mkpath Pathname#rmtree
Pathname#mkpathの戻り値をレシーバにしたいという提案Pathname#mkpathはパスのディレクトリを生成するメソッド- https://docs.ruby-lang.org/ja/latest/method/Pathname/i/mkpath.html
Pathnameのインスタンスを生成しつつ#mkpathを呼び出す場合、次のように#tapする必要がある
# Pathname のインスタンスを生成しつつ mkpath でディレクトリも作成したい # #mkpath の戻り値は nil なので tap を経由する必要がある path = Pathname.new("/tmp/new").tap(&:mkpath)
Pathname#mkpathの戻り値をレシーバにすることで次のようにかける
path = Pathname.new("/tmp/new").mkpath
- 戻り値が
nilからPathnameに変わるが依存してるコードはなさそうらしい
[Feature #17312] New methods in Enumerable and Enumerator::Lazy: flatten, product, compact
Enumerator::Lazyに#compact#product#flattenを追加する提案- あると便利そう
[Feature #17314] Provide a way to declare visibility of attributes defined by attr* methods in a single expression
- 以下の2つの変更を提案するチケット
attr_xxxの戻り値を引数の名前の配列にする提案
attr_reader :id, :name, :age # 今 => nil # 提案 => [:id, :name, :age]
public/protected/privateの引数に配列を渡せるようにする提案
# 提案 private [:id, :name, :age]
- この2つを取り入れると以下のように
private+attr_xxxを組み合わせる事ができる
class Foo private attr_accessor :foo, :bar end
# 独自のラッパーメソッドを介したりとか class Module def traceable(names) # ... names end end class Foo traceable attr_accessor :foo # it can be mixed with public/protected/private too protected traceable attr_accessor :bar end
- この手の提案は定期的に出てきてて以下のチケットとかだと
attr_xxxの戻り値を変えてprivate *attr_accessor :foo, :barにかけるような提案とかされている
[Feature #17316] On memoization
- Ruby でメモ化する場合、以下のようなコードを書く場合が多い
@foo ||= some_heavy_calculation(...)
- しかし、厳密には以下のように『インスタンス変数が定義されているかどうか』で判定する必要がある
unless instance_variable_defined?(:foo) @foo = some_heavy_calculation(...) end
- こういうコードは冗長であまり書きたくないのでもっと簡略化して書きたいという提案
- 例えば以下のように
#instance_variable_setでブロックを受け取るようにしたりとか
instance_variable_set(:foo){ some_heavy_calculation(...) }
- もしくは
#memoizeみたいなヘルパメソッドを定義するとか
memoize(:foo){ some_heavy_calculation(...) }
- 機能としては欲しいんだけど、どういうような書き方にするのかは無限にむずかしそう…
[PR #3740] Speed up ivar set
aaron@whiteclaw ~/g/ruby (init-ivars)> ruby -v test.rb
ruby 3.0.0dev (2020-11-05T19:13:04Z master ab5f2fa4fb) [x86_64-linux]
Warming up --------------------------------------
init 523.589k i/100ms
Calculating -------------------------------------
init 5.281M (± 0.4%) i/s - 26.703M in 5.056507s
aaron@whiteclaw ~/g/ruby (init-ivars)> ./ruby -v test.rb
ruby 3.0.0dev (2020-11-06T18:37:08Z init-ivars 014059c3cb) [x86_64-linux]
Warming up --------------------------------------
init 547.661k i/100ms
Calculating -------------------------------------
init 5.444M (± 0.4%) i/s - 27.383M in 5.030236s
aaron@whiteclaw ~/g/ruby (init-ivars)> cat test.rb
require "benchmark/ips"
class Foo
def initialize
@a = nil
@b = nil
@c = nil
@d = nil
end
end
Benchmark.ips do |x|
x.report("init") { Foo.new }
end
[Feature #17322] Deprecate Random::DEFAULT and introduce Random.default() method to provide Ractor-supported default random generator
- デフォルトの疑似乱数生成器を返す
Random::DEFAULTという定数がある - これはスレッドセーフではないため Ractor ごとに疑似乱数生成器が参照できないぽい
- 複数の Ractor から参照するとエラーになる
- 複数の Ractor で利用できるように
Random.default()というメソッドを新しく追加する提案 - それに伴い
Random::DEFAULTは Deprecate にする- なので Ractor ないでは
Random::DEFAULTはしないようにする
- なので Ractor ないでは
Thread#[]みたいに Ractor ごとの固有の変数を定義するようにしてはどうか、とコメントがある- 例えば
Ractor.current[:DEFAULT_RANDOM]みたいな - https://bugs.ruby-lang.org/issues/17322#note-3
- 例えば
[Feature #17315] Hash #transform
- Hash の要素を変更して Hash を返す
Hash#transformメソッドの提案
h = {'name' => 'dominic ', 'email' => 'dominic.mail.com '}
# キーを String から Symbol に変換する
h.transform!{|k,v| [k.to_sym, v.strip]}
h # => {name: 'dominic', email: 'dominic.mail.com'}
Hash#mapだと Hash ではなくて Array を返すので Hash を返すメソッドはほしい- 一応、副作用がない版は
Hash#to_hでも代用可能
h = {'name' => 'dominic ', 'email' => 'dominic.mail.com '}
# キーを String から Symbol に変換する
p h.to_h { |k,v| [k.to_sym, v.strip] }
# => {:name=>"dominic", :email=>"dominic.mail.com"}
# レシーバは元のまま
p h
# => {"name"=>"dominic ", "email"=>"dominic.mail.com "}
- なるほどね?
merge, fix されたチケット
- [[PR #3740] Speed up ivar set])(https://github.com/ruby/ruby/pull/3740)
- インスタンス変数の設定のパフォーマンスアップ