2022/05/26 今回の気になった bugs.ruby のチケット
今週は Refinements で protected
されたメソッドが呼び出せないバグ報告がありました。
[Bug #18806] protected methods defined by refinements can't be called
- Refinements で定義された
protected
がメソッドが呼び出せないというバグ報告
class A end module MyRefine refine A do private def private_foo "refined" end def private_foo_in_refinement private_foo end protected def protected_foo "refined" end def protected_foo_in_refinement # この呼び出しがエラーになる protected_foo end end end class A using MyRefine def call_private private_foo end def call_private_through_refinement private_foo_in_refinement end def call_protected # この呼び出しがエラーになる protected_foo end def call_protected_through_refinement protected_foo_in_refinement end def is_defined # defined? だとメソッドが定義されているように振る舞う defined?(protected_foo) end end pp A.new.call_private # => :refined pp A.new.call_private_through_refinement # => :refined pp A.new.call_protected # => NoMethodError: protected method `protected_foo' called for #<A:0x00007f23f35e9390> pp A.new.call_protected_through_refinement # => NoMethodError: protected method `protected_foo' called for #<A:0x00007f23f35e9390> pp A.new.is_defined # "method"
- 久々に Refinement のバグみたな?
- これ、今まで見つかってなかったんだ…
protected
でも問題なくprotected
のメソッドとして呼び出せるのが期待する挙動な気がする
[Bug #18793] Select and Find behave differently for hashes
- 以下のように
Hash#select
とHash#find
で挙動が違うというバグ報告
# キーにマッチした結果が返ってくる { 1..10 => :a, 11 .. 20 => :b }.select { _1 === 12 } # => {11..20=>:b} # しかし find の場合は見つからない { 1..10 => :a, 11 .. 20 => :b }.find { _1 === 12 } # => nil # select の _1 はキーを受け取る { 1..10 => :a, 11 .. 20 => :b }.select { p _1 } # => 1..10 # 11..20 # find は [キー, 要素] の配列を受け取る { 1..10 => :a, 11 .. 20 => :b }.find { p _1 } # => [1..10, :a]
_1
ではなくて{ |k,| }
のように,
を付けてブロックの引数を受け取ると配列の第一要素のみを受け取るので両方共同じ挙動になる
# キーにマッチした結果が返ってくる p({ 1..10 => :a, 11 .. 20 => :b }.select { |k,| k === 12 }) # => {11..20=>:b} # しかし find の場合は見つからない p({ 1..10 => :a, 11 .. 20 => :b }.find { |k,| k === 12 }) # => [11..20, :b] # select の _1 はキーを受け取る { 1..10 => :a, 11 .. 20 => :b }.select { |k,| p k } # => 1..10 # 11..20 # find は [キー, 要素] の配列を受け取る { 1..10 => :a, 11 .. 20 => :b }.find { |k,| p k } # => 1..10
[Bug #18771] IO.foreach/.readlines ignores the 4th positional argument
IO.readlines
の引数シグネチャは以下のようになっている
readlines(name, sep, limit [, getline_args, open_args]) → array
- 位置引数を3つ受け取って、残りはキーワード引数で受け取るが、位置引数を4つ渡してもエラーにならないというバグ報告
ArgumentError
になるのが期待する挙動
File.readlines('file.txt', "\n", 10) # => ["abc\n", "\n", "def\n"] File.readlines('file.txt', "\n", 10, {}) # => ["abc\n", "\n", "def\n"] File.readlines('file.txt', "\n", 10, {chomp: true}) # => ["abc\n", "\n", "def\n"] File.readlines('file.txt', "\n", 10, false) # => ["abc\n", "\n", "def\n"] File.readlines('file.txt', "\n", 10, nil) # => ["abc\n", "\n", "def\n"]
- るりまの表記だと以下の通り
readlines(path, rs = $/, chomp: false, opts={}) -> [String] readlines(path, limit, chomp: false, opts={}) -> [String] readlines(path, rs, limit, chomp: false, opts={}) -> [String]
- RDoc だと以下の通り
readlines(name, sep=$/ [, getline_args, open_args]) → array readlines(name, limit [, getline_args, open_args]) → array readlines(name, sep, limit [, getline_args, open_args]) → array readlines(name, sep=$/ [, getline_args, open_args]) → array readlines(name, limit [, getline_args, open_args]) → array readlines(name, sep, limit [, getline_args, open_args]) → array
[Bug #18797] Third argument to Regexp.new is a bit broken
Regexp.new
の第三引数が壊れているというバグ報告- 第二引数との挙動が違っているらしい
Regexp.new
の第二引数にRegexp::NOENCODING
を渡すとn
オプションと同じ挙動になる- 正規表現のマッチ時に文字列のエンコーディングを無視し、バイト列としてマッチする
- Regexp::NOENCODING (Ruby 3.1 リファレンスマニュアル)
- このオプションの時に
ASCII
文字以外を渡すとエラーになるぽい?
# OK Regexp.new('abc', Regexp::NOENCODING) # error: /.../n has a non escaped non ASCII character in non ASCII-8BIT script: /あああ/ (RegexpError) Regexp.new('あああ', Regexp::NOENCODING)
Regexp.new
の第三引数は正規表現のエンコーディングを制御する事ができる"n"
,"N"
が与えられた時には、生成された正規表現のエンコーディングはASCII-8BIT
になる- Regexp.compile (Ruby 3.1 リファレンスマニュアル)
- 期待する挙動としては
Regexp::NOENCODING
と同じっぽい?けどRegexp::NOENCODING
とは挙動が異なる事に対して言及しているぽい?
re = Regexp.new('あああ', nil, 'n') # => /あああ/ pp re.options.anybits? Regexp::NOENCODING # => true pp re.encoding # => #<Encoding:ASCII-8BIT> pp re.source.encoding # => #<Encoding:UTF-8> # error: incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string) (Encoding::CompatibilityError) pp re =~ "あああ"
Regexp.new
の引数でどう制御できるのか軽く調べてみたけどあんまりよくわからなかった…