2022/08/04 今回の気になった bugs.ruby のチケット
今週は Enumerator.product
が新しく追加されました。
[Bug #18953] Array#uniq
doesn't evaluate the given block when the size of the array is one
- 配列の要素が1つの場合に
Array#uniq
のブロックが呼ばれないんだけどこれは期待する挙動?というバグ報告
# これはエラーにならないが [1].uniq { aaa } # これはエラーになる # error: undefined local variable or method `aaa' for main:Object (NameError) [1, 2].uniq { aaa }
- これ自体は期待する挙動ぽいですが、実装依存になるんですかね?
- また
Array#sort_by
#max_by
#min_by
は要素が1つの場合でもブロックが呼び出されます
# error: undefined local variable or method `aaa' for main:Object (NameError) [1].sort_by { aaa }
- あと
Enumerable#uniq
は要素が1つの場合でもエラーになるみたいですね
require "set" # 2つともエラーになる Set[1].uniq { aaa } { a: 1 }.uniq { aaa }
[Feature #18950] Hash#slice fails to copy default block
Hash#slice
がデフォルトの proc をコピーして返さないバグ報告
hash_with_default = Hash.new { |h, k| h[k] = {} } # デフォルト proc が設定されている pp hash_with_default.default_proc # => #<Proc:0x00007f7cd0f3c8a8 /tmp/vdmem8a/29:1> # #slice の戻り値はデフォルト proc が設定されていない pp hash_with_default.slice(:a).default_proc # => nil
- これは期待する挙動で
Hash#slice
は新しいHash
オブジェクトを返してその時にデフォルトの proc はコピーされないみたいです - 以下のように
Hash#slice
以外でも同様の挙動
hash_with_default = Hash.new { |h, k| h[k] = {} } pp hash_with_default.except(:a).default_proc # => nil pp hash_with_default.select {}.default_proc # => nil pp hash_with_default.invert.default_proc # => nil
[Bug #18743] Enumerator#next / peek re-use each others stacktraces
- 次のように
Enumerator#peek
とEnumerator#next
がある
enum = [1, 2, 3].each # Enumerator#peek は状態を変化させないで「次」を返す pp enum.peek # => 1 pp enum.peek # => 1 pp enum.peek # => 1 # Enumerator#next は状態を変化させて「次」を返す pp enum.next # => 1 pp enum.next # => 2 pp enum.next # => 3 # 「次」がない場合はエラーになる # error: `next': iteration reached an end (StopIteration) pp enum.next # => 3
- 次のように
peek
で失敗したした後にnext
でエラーになるとバックトレースの行数が正しくないというバグ報告
# enum.rb # 1 # 2 enum = [].each # 3 enum.peek rescue nil # 4 <- エラー行はここを指している enum.next # 5 <- ここでエラーになるが↑
$ ruby enum.rb enum.rb:4:in `peek': iteration reached an end (stopiteration) from enum.rb:4:in `<main>'
- 以下のように複数呼び出した場合も意図しない行数になっている
# enum.rb # 1 # 2 enum = [].each # 3 enum.peek rescue nil # 4 enum.next rescue nil # 5 enum.peek rescue nil # 6 puts "line #{__line__}" # 7 enum.next # 8
$ ruby enum.rb line 7 enum.rb:4:in `peek': iteration reached an end (stopiteration) from enum.rb:4:in `<main>'
[feature #18685] Enumerator.product: cartesian product of enumerables
- 要素ごとの全ての組み合わせの
Enumerator
を生成するEnumerator.product
を追加する提案
product = Enumerator.product(1..3, ["a", "b"]) p product.class #=> Enumerator product.each do |i, c| puts "#{i}-#{c}" end __end__ output: 1-a 1-b 2-a 2-b 3-a 3-b
- この機能は ruby 3.2 にマージされました