2021/02/25 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[PR #4193] Add Hash#delete_at
Hash#delete_at
を追加する提案- bugs.ruby にまだチケットはなさそう
- 特定のキーの要素を取り除いて、取り除いた要素を返すメソッド
hash = { a: true, b: false, c: nil } # hash から直接要素を取り除きつつ、取り除いた値を返す a, c = hash.delete_at(:a, :c) # => [ true, nil ] hash # => { b: false } # Hash#except は取り除かれた結果を返す hash = { a: true, b: false, c: nil } hash = hash.except(:a, :c) p hash # {:b=>false}
- 取り除いた要素を参照したい場合は便利そう
[PR #207] Support pattern matching in CSV rows
CSV::Row
をパターンマッチに対応させる PR- CSV の行ごとにパターンマッチできる
- 以下のようにヘッダーカラムがキーで要素が値になる
header = [:id, :name, :age] case CSV::Row.new(header, [1, "homu", 14]) in name:, age: name # => "homu" age # => 14 end
- これは普通に便利そう
- こういうパターンマッチ対応って今後流行っていくんですかねー
[Bug #17590] M.prepend M
has hidden side effect
- 先週話していたバグ
- 以下のように
M.prepend M
を呼んだ場合に副作用あるバグが修正された
module M; end class C; end C.prepend M C.include M # これを読んだ時に失敗するが、副作用があった M.prepend M rescue nil module M2; end M2.prepend M C.include M2 p C.ancestors # 3.0 => [M, C, M2, M, M2, Object, Kernel, BasicObject] # 3.1 => [M, C, M2, Object, Kernel, BasicObject]
[Bug #17649] defined?
invokes method once for each syntactic element around it
defined?
の式で複数回メソッドが呼ばれることがあるというバグ報告- 以下の例だと
x
メソッドがdefined?
時に複数回呼ばれることがある
public def x $times_called += 1 end def times_called $times_called = 0 yield $times_called end # without `defined?` times_called { x } # => 1 times_called { -x } # => 1 times_called { --x } # => 1 times_called { ---x } # => 1 times_called { x+0+0 } # => 1 times_called { x.pred.pred } # => 1 times_called { x.x.x.x.x.x } # => 6 # with `defined?` times_called { defined? x } # => 0 times_called { defined? -x } # => 1 times_called { defined? --x } # => 2 times_called { defined? ---x } # => 3 times_called { defined? x+0+0 } # => 2 times_called { defined? x.pred.pred } # => 2 times_called { defined? x.x.x.x.x.x } # => 15
- これは
defined? a.b.c.d
を呼び出した時にa
a.b
a.b.c
a.b.c.d
が個別に呼び出されしまっているからのようです
puts RubyVM::InstructionSequence.new("defined? a.b.c.d").disasm __END__ output: == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,16)> (catch: TRUE) == catch table | catch type: rescue st: 0001 ed: 0039 sp: 0000 cont: 0041 | == disasm: #<ISeq:defined guard in <compiled>@<compiled>:0 (0,0)-(-1,-1)> (catch: FALSE) | local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) | [ 1] $!@0 | 0000 putnil | 0001 leave |------------------------------------------------------------------------ 0000 putnil ( 1)[Li] 0001 putself 0002 defined func, :a, false 0006 branchunless 41 0008 putself 0009 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0011 defined method, :b, false 0015 branchunless 41 0017 putself 0018 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0020 opt_send_without_block <calldata!mid:b, argc:0, ARGS_SIMPLE> 0022 defined method, :c, false 0026 branchunless 41 0028 putself 0029 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0031 opt_send_without_block <calldata!mid:b, argc:0, ARGS_SIMPLE> 0033 opt_send_without_block <calldata!mid:c, argc:0, ARGS_SIMPLE> 0035 defined method, :d, true 0039 swap 0040 pop 0041 leave
- 修正 PR が投げられているので特に問題がなければ修正されそう