2021/06/17 今週の気になった bugs.ruby のチケット
今週は ENV
に対して変更が入りました。
[Bug #17098] Float#negative? reports negative zero as not negative
-0.0
がFloat#negative?
でfalse
を返すのは期待しているのか?というバグ報告- IEEE 754 の規格?でそう定まってるらしい?
neg_zero = -0.0 pp neg_zero.negative? # => false pp neg_zero < 0 # => false
- チケットを立てた人が期待する動作としてはこう
-0.0.negative? # => true 0.0.positive? # => false
- その他、現状の挙動
pp RUBY_VERSION # => "3.0.1" # これは両方共 true pp 0.0 == 0.0 # => true pp -0.0 == -0.0 # => true # equal? の場合 pp 0.0.equal?(0.0) # => true pp -0.0.equal?(-0.0) # => false # 変数に代入してから比較すると a = -0.0 pp a.equal?(a) # => true puts "---" # -0.0 か判定する方法 # https://bugs.ruby-lang.org/issues/17098#note-7 def check_negative_zero(f) 1.0 / f == -Float::INFINITY end pp check_negative_zero(-0.0) # => true pp check_negative_zero(0.0) # => false
- また
Float#signbit
を追加するようなコメントをされている - 実際
0.0
と-0.0
を区別したいユースケースってあるんですかね
[Feature #17950] Unable to pattern-match against a String key
- パターンマッチでキーが
String
の場合にエラーになるというバグ報告
# Hash のキーに文字列がある場合、マッチする事ができない case { status: 200, headers: {"content-type" => "application/json"}, body: "bla" } in { status: , headers: { "content-type" => type }, body: } end # syntax error, unexpected terminator, expecting literal content or tSTRING_DBEG or tSTRING_DVAR or tLABEL_END # ...tus: , headers: {"content-type" => type}, body: }
- これは現時点では仕様
- ちなみにこういう風に書くことは可能
- 可能なだけで書きたくはないなあ
case { status: 200, headers: {"content-type" => "application/json"}, body: "bla" } in { status: , headers: headers, body: } if type = headers["content-type"] pp type # => "application/json" end
- 早くパターンマッチ使いたい
[Bug #17767] Cloned ENV
inconsistently returns ENV
or self
ENV
とENV.clone
したオブジェクトで挙動に一貫性がないというバグ報告
cloned_env = ENV.clone p ENV.each_key{}.equal?(ENV) #=> true p cloned_env.each_key{}.equal?(cloned_env) #=> true ENV.delete('TEST') err = ENV.fetch('TEST') rescue $! p err.receiver.equal?(ENV) #=> true err = cloned_env.fetch('TEST') rescue $! p err.receiver.equal?(cloned_env) #=> false ENV['TEST'] = 'TRUE' p ENV.select!{ false }.equal?(ENV) #=> true cloned_env['TEST'] = 'TRUE' p cloned_env.select!{ false }.equal?(cloned_env) #=> false
- このチケットがきっかけで Ruby 3.1 から以下のように挙動が変わった
ENV.dup
を使うと例外が発生するENV.clone
を使うと警告がでる- 詳細はこちら : https://blog.n-z.jp/blog/2021-06-12-ruby-env.html
[Bug #17951] Collisions in Proc#hash values for blocks defined at the same line
Proc#hash
の値が同じ値になるケースがあるというバグ報告
require 'set' def capture(&block) block end # 同じブロックを大量に生成する blocks = Array.new(1000) { capture { :foo } } hashes = blocks.map(&:hash).uniq ids = blocks.map(&:object_id).uniq equality = blocks.map { blocks[0].eql?(_1) }.tally hash = blocks.to_h { [_1, nil] } set = blocks.to_set # hash が一意であれば hashes.size == 1000 になるはずだがなっていない puts(hashes.size) # => 11 puts(ids.size) # => 1000 puts(equality.inspect) # => {true=>1, false=>999} puts(hash.size) # => 1000 puts(set.size) # => 1000
- このバグはまだマージされていないが PR は作成され済み
[Bug #15993] 'require' doesn't work if there are Cyrillic chars in the path to Ruby dir
D:\users\киї\Ruby\2.6\bin>ruby -v ruby 2.6.3p62 (2019-04-16 revision 67580) [x64-mingw32] D:\users\киї\Ruby\2.6\bin>ruby -e "require 'logger'" Traceback (most recent call last): 1: from <internal:gem_prelude>:2:in `<internal:gem_prelude>' <internal:gem_prelude>:2:in `require': No such file or directory -- D:/users/РєРёС—/Ruby/2.6/lib/ruby/2.6.0/rubygems.rb (LoadError)
D:\Евгений>C:\Ruby26-x64\bin\ruby -I D:\Евгений -e "require 'logger'" Traceback (most recent call last): 2: from -e:1:in `<main>' 1: from C:/Ruby26-x64/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' C:/Ruby26-x64/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': No such file or directory -- D:/Евгений/logger.rb (LoadError) D:\Евгений>C:\Ruby27-x64\bin\ruby -I D:\Евгений -e "require 'logger'" D:\Евгений>C:\Ruby30-x64\bin\ruby -I D:\Евгений -e "require 'logger'"
- どうやって直ったのかが気になる…