2022/04/09 今回の気になった bugs.ruby のチケット
今週は MatchData#[]
のバグ報告などがありました。
[Bug #18670] MatchData#[start, length] pads nil values when negative start is given
MatchData#[]
にマイナス値を渡すとnil
で埋めされた配列を返すバグ報告
# [-1, 5] は最後の値から5文字分を返す # String#[] や Array#[] は結果的に最後の値だけを返す pp "hello"[-1, 5] # => "o" pp [1, 2, 3][-1, 5] # => "3" # MatchData#[] の場合は足りない値が nil 埋めされた配列を返す result = /.*/.match("aaaa") pp result # => #<MatchData "aaaa"> pp result[-1, 5] # => ["aaaa", nil, nil, nil, nil]
- このバグは修正済み
# MatchData#[] の場合は足りない値が nil 埋めされた配列を返す result = /.*/.match("aaaa") pp result[-1, 5] # Ruby 3.1 => ["aaaa", nil, nil, nil, nil] # Ruby 3.2 => ["aaaa"]
[Feature #18683] Allow to create hashes with a specific capacity.
Hash
オブジェクトを生成する時にオブジェクトのサイズを指定できるようにする提案- 更に
rb_hash_new_capa(long)
も拡張する必要がある
- 更に
hash = Hash.new(capacity: 1000)
String
やArray
には同様の機能があるのでHash
にも欲しいという意図らしい
String.new(capacity: XXX) Array.new(XX) / rb_ary_new_capa(long)
- 以下の箇所にメリットがあるとの事
[Bug #18677] BigDecimal#power (**) returns FloatDomainError when passing an infinite parameter
BigDecimal#power (**)
に無限大を渡すと意図しないエラーになるというバグ報告
require "bigdecimal" # error: `**': Computation results in 'Infinity' (FloatDomainError) BigDecimal(10) ** BigDecimal("Infinity")
- サンプル実装も書かれているんですが意図としては
BigDecimal::INFINITY
を返してほしい感じですかね?
require "bigdecimal/util" class BigDecimal < Numeric def **(other) if other.infinite? == 1 if self > 1 BigDecimal::INFINITY elsif self == 1 self elsif self >= 0 BigDecimal(0) else power(other) end else power(other) end end end def puts_and_eval(string) puts string p eval(string) end puts_and_eval "10 ** BigDecimal::INFINITY" # => Infinity puts_and_eval "1 ** BigDecimal::INFINITY" # => 0.1e1 puts_and_eval "0.1 ** BigDecimal::INFINITY" # => 0.0 puts_and_eval "0 ** BigDecimal::INFINITY" # => 0.0 puts_and_eval "-1 ** BigDecimal::INFINITY" # => -0.1e1
[Bug #18673] Anonymous block forwarding fails when combined with keyword arguments
- 以下のようにキーワード引数が定義されている時に匿名のブロック引数を別のメソッドに渡すとエラーになるバグ報告
def inner "yielded #{yield}" end def block_only(&) # OK inner(&) end def pos_arg(arg1, &) # OK inner(&) end def kwarg(arg1, kwarg1:, &) # NG inner(&) end def kwarg_with_default(arg1, kwarg1: "kwarg_default", &) # NG inner(&) end
- このバグは修正済み
[Bug #18415] String#rpartition is not sufficiently greedy compared to String#partition
- 以下のような貪欲な正規表現を
String#rpartition
に渡すと意図する値が返ってこないバグ報告
# [最初のセパレータより前の部分, セパレータ, それ以降の部分] を返す pp "...123...".partition /\d+/ # => ["...", "123", "..."] # [最後のセパレータより前の部分, セパレータ, それ以降の部分] を返すが意図した値ではない pp "...123...".rpartition /\d+/ # => ["...12", "3", "..."]
- これは意図する挙動らしくてドキュメントにその意図を追記する対応がされている
- ちなみに以下のような正規表現だと
123
がセパレータになる
pp "...123...".rpartition(/(?<!\d)\d+/) # => ["...", "123", "..."]