2021/01/07 今週の気になった bugs.ruby のチケット
内容は適当です。
今週と言っても今週みかけたチケットなだけでチケット自体は昔からあるやつもあります。
あくまでも『わたしが気になったチケット』で全ての bugs.ruby のチケットを載せているわけではありません。
[Feature #17471] send_if method for improved conditional chaining
- 以下のような
#send_if
を追加する提案
class Object def send_if(method, *args, proc: nil) yield(self) ? self.send(method, *args, &proc) : self end end
- これは以下のように『条件にマッチしたときのみメソッドチェーンを行う』ような場合に利用できる
puts 'Do you want a loud Merry Christmas? (y or I take it as a no)' answer = gets.chomp # 標準入力を受け取り、入力によって呼び出す処理を切り替える # 'y' が入力されたら大文字に変換して結合する puts %w(Merry Christmas).send(:map, &->(e) { answer == 'y' ? e.upcase : e }).join(' ') # 提案されている send_if ならこんな感じで記述できる puts %w(Merry Christmas).send_if(:map, proc: :upcase) { answer == 'y' }.join(' ')
- わたしもこういうのがほしいと思っていていろいろと考えているんですが今回の
#send_if
はかなりやってることが多くて個人的にはちょっと微妙- とはいえこうなってしまう理由もわかるのでうーーーーんって感じ
条件
と条件にマッチした場合の処理
の2つのブロックをメソッドに渡したいんですが Ruby でこのあたりどう表現すべきなのかが難しい
- ちなみに個人的には以下のような
tap + break
でいいじゃん、ってなっています
# Proposal puts %w(Merry Christmas).send_if(:map, proc: :upcase ) { answer == 'y' }.join(' ') # tap + break puts %w(Merry Christmas).tap { break _1.map(&:upcase) if answer == 'y' }.join(' ')
tap + break
に慣れてないとぎょっとするんですが、これはこれで Ruby としてみるとかなり素直なコードになっているので個人的には気に入っています- また似たようなチケットとしては以下のようなチケットもあるので気になる人はこちらも見てみると良いです
[Bug #17512] ostruct super regression
- 以下のように
super
を経由してOpenStruct
を参照した場合に Ruby 3.0 だと意図しない値が返ってきているというバグ報告
require 'ostruct' class Foo < OpenStruct def foo super end end p Foo.new(foo: 123).foo # Ruby 2.7 => 123 # Ruby 3.0 => nil
- この問題は
OpenStruct 0.3.2
で修正されている - 困っている人は個別に
OpenStruct
をインストールすると改善すると思います
[Misc #16436] hash missing #last method, make it not so consistent (it has #first)
Hash#first
はあるけどHash#last
はないので一貫性がないよねーっていうチケット
homu = { id: 1, name: "homu", age: 14 } pp homu.first # => [:id, 1] # error: undefined method `last' for {:id=>1, :name=>"homu", :age=>14}:Hash (NoMethodError) pp homu.last
- これは
Hash#first
はEnumerable#first
で実装されておりEnumerable#last
がないからですEnumerable#first
があってEnumerable#last
がないのは知らなかった- まあ確かにイテレーションを考えると
#first
はあっても#last
がないのはなんとなくわかるよな…?
- ちなみに以下のように
#reverse_each
を使うと終端の要素を取得することはできます
homu = { id: 1, name: "homu", age: 14 } pp homu.reverse_each.first # => [:age, 14]
- このチケット自体には強い気持ちでの要望とかはないので、もし必要な人とかがいればコメントしてみるといいと思います
[Bug #17488] Regression in Ruby 3: Hash#key? is non-deterministic when argument uses DelegateClass
- 次のように Ruby 3.0 で
Hask#key?
にDelegateClass
を渡すと意図しない結果が返ってくるというバグ報告- Ruby 3.0 では
Hask#key?
の結果が起動毎に変わることがある
- Ruby 3.0 では
puts "Running on Ruby: #{RUBY_DESCRIPTION}" program = <<~EOS require "delegate" TypeName = DelegateClass(String) hash = { "Int" => true, "Float" => true, "String" => true, "Boolean" => true, "WidgetFilter" => true, "WidgetAggregation" => true, "WidgetEdge" => true, "WidgetSortOrder" => true, "WidgetGrouping" => true, } puts hash.key?(TypeName.new("WidgetAggregation")) EOS iterations = 20 results = iterations.times.map { `ruby -e '#{program}'`.chomp }.tally # Ruby 3.0 で実行すると false が返ってくることがある puts "Results of checking `Hash#key?` #{iterations} times: #{results.inspect}" # Ruby 2.7 => Results of checking `Hash#key?` 20 times: {"true"=>20} # Ruby 3.0 => Results of checking `Hash#key?` 20 times: {"false"=>12, "true"=>8}
- この問題は開発版ではすでに修正済みです
[Bug #17481] Keyword arguments change value after calling super without arguments in Ruby 3.0
- 次のように
super
を呼び出す前と後でキーワード引数の値が変わってしまうというバグ報告
class BaseTest def call(a:, b:, **) end end class Test < BaseTest def call(a:, b:, **options) p options # => {:c=>{}} super # super を呼び出した後で options の値が変わってしまっている… p options # => {:c=>{}, :a=>1, :b=>2} end end Test.new.call(a: 1, b: 2, c: {})
- どうして…どうして…
- この問題は
Ruby 3.0
で再現しており開発版ではすでに修正済みです
[Feature #17472] HashWithIndifferentAccess like Hash extension
ActiveSupport::HashWithIndifferentAccess
をサポートする機能を Ruby で実装する?というチケット- ちょっとチケットの意図が読み取れてないので間違ってるかもしれませんが『Ruby 本体で
ActiveSupport::HashWithIndifferentAccess
を実装する(提供する)』というわけではなくて『`ActiveSupport::HashWithIndifferentAccess
を高速化できる仕組みを Ruby 側で用意する』っていうのが趣旨なのかな? - 具体的に言うと Ruby 3.0 で追加された
Symbol#name
みたいなのを Ruby 本体でActiveSupport::HashWithIndifferentAccess
を高速化できるような機能を提供する感じなんですかね- コメント読んでる限りこのあたりちょっと認識のズレがありそう
- 最初読んだ時に『
ActiveSupport::HashWithIndifferentAccess
を Ruby で提供するのはやめてくれ〜〜〜』と思っていたんですが機能提供って意味だとかなりよさそうですね
[RP] Remove deprecated URI.escape/URI.unescape
- 長らく非推奨だった
URI.escape
/URI.unescape
が Ruby 3.0 から削除された - 今後は代替として
ERB::Util.#url_encode
やCGI.escape
などを利用していく必要がある - 参照