2020/12/24 今週の気になった bugs.ruby のチケット

内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。

[Bug #17030] Enumerable#grep{_v} should be optimized for Regexp その後

  • 以前紹介した ary.select { |e| e.match?(reg) } と比較して ary.grep(reg) の方が遅いので最適化しよう、という提案
  • その後、議論が進んで最終的に ary.grep(reg) のようにブロック引数がない場合は MatchData を生成しないように対応された
ary = ["homu", "mami", "mado"]

reg = /.*/
ary.grep(reg)
# or Regexp.last_match
p $~
# 2.7 => #<MatchData "mado">
# 3.0 => nil

# ブロックを渡した場合は MatchData を生成する
ary.grep(reg) {}
# or Regexp.last_match
p $~
# 2.7 も 3.0 => #<MatchData "mado">
  • この挙動は非互換な変更になるので注意する必要がります

[PR #124] Add measure command

  • irbmeasure というコマンドが追加された
  • これは measure を呼び出した以降で実行時間を出力するような事を行う
irb(main):001:0> 3
 => 3
irb(main):002:0> measure
TIME is added.
 => nil
irb(main):003:0> 3
processing time: 0.000058s
 => 3
irb(main):004:0> measure :off
 => nil
irb(main):005:0> 3
 => 3
  • また以下のようにカスタマイズすることも可能です
IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |context, code, line_no, &block|
  time = Time.now
  result = block.()
  now = Time.now
  puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
  result
}
  • これは普通に便利そう

[Bug #17428] Method#inspect bad output for class methods

  • Method#inspect の内容がおかしいというバグ報告
  • 次のようにクラス名が表示されないケースがある
p String.method(:prepend)
# 2.7 => #<Method: String.prepend(*)>
# 3.0 => #<Method: #<Class:Object>(Module)#prepend(*)>
  • この問題は最新版では以下のように修正された
p String.method(:prepend)
# 2.7 => #<Method: String.prepend(*)>
# 3.0 => #<Method: #<Class:String>(Module)#prepend(*)>
  • これは気づかなかった…

[Feature #17116] raise ArgumentError in Enumerator#new in no given blocks

  • Enumerator.new(obj) みたいに .new にブロックを渡さない場合は deprecated warning が出ている
    • この警告がでているのは Ruby 2.0 の頃から
obj = Object.new
# warning: Enumerator.new without a block is deprecated; use Object#to_enum instead
Enumerator.new(obj)
  • これはもうエラーにしてしまってもいいんじゃないか、というチケット
  • これはマージされて Ruby 3.0 からはエラーになるので注意しましょう

[Bug #17423] Prepend should prepend a module before the class

  • Ruby 3.0 では以下のように prepend の挙動が変わってしまう事がある
module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

# B.prepend M してるのに M が B よりもあとに来る
p B.ancestors
# 2.7 => [M, B, A, Object, Kernel, BasicObject]
# 3.0 => [B, M, A, Object, Kernel, BasicObject]
  • これを次のように M が重複するようにするという内容のチケット
module M; end
module A; end
class B; include A; end

A.prepend M
B.prepend M

# このように修正する
p B.ancestors
# => [M, B, M, A, Object, Kernel, BasicObject]
  • この問題は Ruby 3.0 リリース後に対応される予定です
  • ちなみにこのチケットはまつもとさん自身が建てています

[Feature #17411] Allow expressions in pattern matching

  • パターンマッチでは次のようにパターンの部分に式を書くことができません
user = { name: "homu", age: 14 }
case user
# syntax error, unexpected '+', expecting ')'
# パターンに式を記述する事ができない
in { age: (7 + 7) }
end
  • これを ^(expression) のようにかけるようにしようという提案
user = { name: "homu", age: 14 }
case user
# OK
# 式を書く場合は ^() を使う
in { age: ^(7 + 7) }
end

[Bug #17398] SyntaxError in endless method

  • Ruby 3.0 のエンドレスメソッド定義で次のような定義の場合シンタックスエラーになる、という旨のチケット
# OK
def hoge = puts("homu")

# syntax error, unexpected string literal, expecting `do' or '{' or '('
def hoge = puts "homu"