2021/04/01 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[Bug #17757] Hash#slice does not keep compare_by_identity on the results
Hash#compare_by_identity
を使用するとレシーバの Hash をキーの一致判定をオブジェクトの同一性で判定するようにするObject#object_id
で判定するようにする
hash = { "a" => 1, b: 2 } # デフォルトでは無効 p hash.compare_by_identity? # => false # OK p hash["a"] # => 1 p hash[:b] # => 1 # Object#object_id で判定するようにする hash.compare_by_identity p hash.compare_by_identity? # => true # ハッシュのキーの "a" と 参照するときの "a" の object_id は異なるので参照できない p hash["a"] # => nil # Symbol は同じ object_id なので参照できる p hash[:b] # => 2
- この
compare_by_identity
だが特定のメソッドを経由して生成した Hash でcompare_by_identity
の性質を受け継いだりしなかったりするというバグ報告
hash = { "a" => 1, b: 2 } # Object#object_id で判定するようにする hash.compare_by_identity # こっちは compare_by_identity を保持するが p hash.except("a").compare_by_identity? # => true # こっちは compare_by_identity を保持しない p hash.slice("a").compare_by_identity? # => false
- なるほど…?
compare_by_identity
なんてものがあるの知らなかった
[Bug #17754] NoMethodError#to_s makes segmentation fault when Module#name returns non string value
- 以下のように
.name
が文字列以外を返した場合に SEGV するというバグ報告
class C def self.name 42 # これなら OK # "42" end end # C に対して NoMethodError なエラーが発生すると SEGV する C.this_method_does_not_exist
- これは Ruby 3.0 で再現して 2.7 や 2.6 では再現しなかった
- 3.1.0-dev で既に修正済み
- よく見つけるなあこんなバグ…
[Bug #17756] StringScanner#charpos makes segmentation fault when target.byteslice returns non string value
- 以下のように
StringScanner
を使用すると SEGV するというバグ報告byteslice
を上書きしてnil
を返すと落ちるっぽい?
require 'strscan' string = 'ruby' scnanner = StringScanner.new(string) pre = Module.new do def byteslice(*args) end end string.singleton_class.prepend(pre) scnanner.charpos
- これは既に対応済み
- そもそも
StringScanner
の存在を知らなかった- 指定した文字列をスキャンするためのライブラリ
- Ruby | StringScanner で字句解析 - Qiita
- Rubyの標準ライブラリStringScannerがすごい! - hythofの日記
[Feature #17753] Add Module#outer_scope
- 自分が定義されている1つ上のスコープのオブジェクトを取得する
Module#outer_scope
メソッドの提案
module A module B class C; end class D; end end end # C が定義されている箇所のスコープを返す p A::B::C.outer_scope # => B # ネストして呼び出したりとか p A::B::C.outer_scope.outer_scope # => A
- ユースケースとしては次のように同じスコープの定数を列挙したい場合に利用できる
A::B::C.outer_scope.constants # => [A::B::C, A::B::D] ObjectSpace.each_object(Class) do |k| p siblings: k.outer_scope.constants end
- 現在は『
outer_scope
って名前じゃなくてnamespace
のほうがいいんじゃない?』と言われてModule#namespace
って名前になっている- https://bugs.ruby-lang.org/issues/17753#note-2
- 流石に
Module#namespace
って名前をここで使っちゃうのはなんかもったいない気がするなあ…
[Feature #17749] Const source location without name
Module#const_source_location
を『レシーバ』に対して行う機能を追加する提案A::B.const_source_location
はA.const_source_location(:B)
と同じ意味になる- PR: https://github.com/ruby/ruby/pull/4324
- Module#const_source_location (Ruby 3.0.0 リファレンスマニュアル)
module A class B end end p A::B.const_source_location # => ["test.rb", 2] # これと同じ意味 p A.const_source_location(:B) # => ["test.rb", 2] # ユースケース # const_source_location に渡す定数名がわからない場合に利用できる ObjectSpace.each_object(Class) do |k| p k.const_source_location end
- これは普通に前からほしいなーと思ってたのでうれしい
- この機能自体は『定数』とは関係ないので
const_source_location
じゃなくてsource_location
という名前に変わっている
[Feature #17768] Proposal: Downward assignments
- 次のように変数を下の行で定義する提案
# var = 42 と同じ 42 ^^var # 中間の式も代入できる p(2 * 3 * 7) #=> 42 ^^^^^var p var #=> 6
- 実際のユースケースいろいろ
while (line = gets) != nil p line end # ↓↓↓ while gets != nil ^^^^line p line end
ary = [1, 2, 3, 4, 5] ary.each {|elem| found = elem if elem.even? } p found #=> 4 # ↓↓↓ ary = [1, 2, 3, 4, 5] ary.each {|elem| elem if elem.even? } ^^^^found p found #=> 4
class C def initialize(foo, bar) @foo = foo @bar = bar end end # ↓↓↓ class C def initialize(foo, bar) ^^^@foo ^^^@bar end
- めっちゃ便利そうじゃん…(※もちろんこれはエイプリルフールネタです
- ちゃんと patch ファイルも付いてて以下のコードは普通に動いてる
(2 * 3 * 7) ^^^^^var p var while gets != nil ^^^^line p line end ary = [1, 2, 3, 4, 5] ary.each {|elem| elem if elem.even? } ^^^^found p found #=> 4
- どうやってやってるの…
[Feature #17769] Proposal: numeric coefficient syntax
2x
を2 * x
と解釈するようにする提案
irb(main):001:0> x = 3 => 3 irb(main):002:0> 2x => 6 irb(main):003:0> def pi = Math::PI => :pi irb(main):004:0> 2pi => 6.283185307179586
2x
だけではなくて2(x + 1)
という風にもかけるらしい- これもエイプリルフールネタ
- patch 内容が比較的シンプルで面白い