2020/10/29 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[PR #3703] Assoc pattern matching
- 1行
in
から=>
に変わった - 今までは
in
を使って1行でパターンマッチを書くことができた
data = { name: "homu", age: 14 } # こういうパターンマッチを case data in { name:, age: } end # 1行 in で書くことができた # 1行 in を使うと分割代入を行うような事ができてた data in { name:, age: } p name # => "homu" p age # => 14
- Ruby 3.0 ではこの1行
in
が削除され代わりに=>
を使って分割代入っぽいコードを書くことができるようになる
data = { name: "homu", age: 14 } data => { name:, age: } p name # => "homu" p age # => 14 # Struct でもキャプチャできる data = Struct.new(:name, :age).new("mami", 15) data => { name: } p name # => "mami" # マッチしなかった場合に raise NoMatchingPatternError が発生する data => { name: Integer }
- 分割代入と言ってるがあくまでもパターンマッチの亜種になるので注意
- 参照:開発版の Ruby 3.0 の右代入で分割代入ができる機能がはいった - Secret Garden(Instrumental)
[Bug #10845] Subclassing String
String
を継承したクラスで特定のメソッドを呼ぶとString
を返したり継承したクラスを返したりバラバラになっている
class MyString < String end # これは MyString のインスタンスを返す p (MyString.new("hoge") * 2).class # => MyString p (MyString.new("hoge") << "foo").class # => MyString # 以下のメソッドは String のインスタンスを返す p (MyString.new("foo") + "bar").class # => String p (MyString.new("%d") % 42).class # => String
- 今のところは
String
を返すように統一するような流れっぽい? String
を返すようにする PR もある
[Bug #6087] How should inherited methods deal with return values of their own subclass?
- 先程の
String の挙動が
Array` にもあるというチケット
class MyArray < Array end # MyArray を返す p MyArray.new.flatten.class # => MyArray p (MyArray.new * 2).class # => MyArray # Array を返す p MyArray.new.rotate.class # => Array p (MyArray.new + MyArray.new).class # => Array
- これも
Array
を返すようにする PR がある
[Bug #11808] Different behavior between Enumerable#grep and Array#grep
Array#grep
で正規表現を渡すとブロック内でマッチした値を参照することができる
# grep の正規表現でマッチした値を $1 で参照できる p %w(homu mami).grep(/(.*)/) { $1 } # => ["homu", "mami"]
- しかし、
include Enumerable
したクラスでは参照できない
class X include Enumerable def each yield "homu" yield "mami" end end p X.new.grep(/(.*)/) { $1 } # => [nil, nil]
- この挙動はバグらしいが直すのが大変らしい
[Bug #17146] Queue operations are allowed after it is frozen
Thread::Queue
をfreeze
しているのに値を変更できるというバグ報告
require "thread" q = Thread::Queue.new.freeze p q.frozen? # => true p q.length # => 0 # freeze されているのに変更できる q << 1 p q.length # => 1
- Ruby 1.6 で
Thread::Queue#freeze
が追加されてからずーっとバグってたっぽい
[Feature #17143] Improve support for warning categories
- [Feature #17122] Add category to Warning#warn で
Warning.warn
で警告のカテゴリを受け取るような機能が追加された
Warning[:deprecated] = true module Warning def self.warn(msg, category: nil) puts "[warning: #{category}] : #{msg}" end end # 警告を出す # [warning: deprecated] : ../ruby/test.rb:11: warning: Object#tainted? is deprecated and will be removed in Ruby 3.2 Object.new.tainted? # deprecated 以外の警告は category が nil # [warning: ] : <internal:ractor>:38: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. Ractor.new {}
- この category を
Kernel.warn
で渡せるようにするという提案
module Warning # ここで category を受け取る事ができる def self.warn(msg, category: nil) puts "[warning: #{category}] : #{msg}" end end def hoge Kernel.warn("warning: hoge is deprecated", category: :deprecated) end # [warning: deprecated] : warning: hoge is deprecated hoge # この設定は反映されないっぽい # これは意図しないかも? Warning[:deprecated] = false # [warning: deprecated] : warning: hoge is deprecated hoge
- また存在しない
category
を渡すとエラーになる
# error: <internal:warning>:43:in `warn': invalid warning category used: hogehoge (ArgumentError) Kernel.warn("warning: hoge is deprecated", category: :hogehoge)
[Feature #17290] Syntax sugar for boolean keyword argument
- 以下のようにキーワード引数
keyword: true
をkeyword:
とかけるようにする提案
gets(chomp: true) CSV.parse(" foo var ", strip: true)
- 上記のコードを以下のようにかけるようにする
gets(chomp:) CSV.parse(" foo var ", strip:)
- 意図としてはフラグを宣言的に書きたいという意図っぽい?
CSV.parse(" foo var ", strip:)
と書いたらstrip
フラグが ON になるようなイメージ
- 流石にこれはつらい。キーワード引数は
true / false
とは限らないので混乱するだけでは…- そもそも
strip: true
はキーワード引数ではなくて Hash で受け取ってる
- そもそも
- ちなみに元のチケットだとマジックコメントも省略できるようにする提案も含まれている
# frozen_string_literal: true # を # frozen_string_literal:
true
を書くのが煩わしいのはわからなくもないけど流石に省略するのではなくて別のアプローチを考えたほうがいいのではないかなあ- 例えば
CSV.parse(" foo var ", strip!!!)
ぐらい極端な構文で書くとか
- 例えば
- このチケットとは関係ないが
hoge(strip:)
と書いたらhoge(strip: strip)
となってほしいという要望もある
merge, fix されたチケット
- [Feature #17260] Promote pattern matching to official feature
- 1行 in の代わりに
=>
で代入できる機能が入った
- 1行 in の代わりに
- [Feature #17143] Improve support for warning categories
Kernel.warn
にcategory
を渡せるようになった
reject されたチケット
- [Feature #17171] Why is the visibility of constants not affected by
private
?private
を定数にも反映させる提案