2021/07/29 今週の気になった bugs.ruby のチケット
Integer.try_convert
の追加や Struct.new.keyword_init?
の追加などがありました。
[Feature #10473] Change Date#to_datetime to use local time
require "date" # ローカルのタイムゾーンを使用しない p Date.new(2014,1,1).to_datetime.to_time # => 2014-01-01 00:00:00 +0000 # to_date や to_time はローカルのタイムゾーンを参照している p Date.new(2014,1,1).to_date.to_time # => 2014-01-01 00:00:00 +0900 p Date.new(2014,1,1).to_time # => 2014-01-01 00:00:00 +0900
p Time.parse('2021-07-23') # => 2021-07-23 00:00:00 +0900 p DateTime.parse('2021-07-23') # => #<DateTime: 2021-07-23T00:00:00+00:00 ((2459419j,0s,0n),+0s,2299161j)>
- また、
to_datetime
でローカルのタイムゾーンを使用するようにすると次の結果が変わってしまう
DateTime.parse(d.to_s) == d.to_datetime
DateTime
自体、互換性のために残されているので非互換にするのは望ましくない、との事- 互換性を保ちつつ対応する場合は
to_datetime
に使用するタイムゾーンを指定するようにするのはどうか、と提案されている
[Bug #18018] Float#floor / truncate sometimes result that is too small.
- 次のように
Float#floor
を使用すると意図しない結果になっているというバグ報告Float#floor
は指定した桁数で小数を切り捨てるメソッド- https://docs.ruby-lang.org/ja/latest/method/Float/i/floor.html
p 291.4.floor(1) # => 291.4 (ok) p 291.4.floor(2) # => 291.39 (not ok) p 291.4.floor(3) # => 291.4 (ok) p 291.4.floor(4) # => 291.4 (ok) p 291.4.floor(5) # => 291.39999 (not ok) p 291.4.floor(6) # => 291.4 (ok)
- この問題は最新版で修正済み
[Bug #18044] unusual behavior with Arabic string in a Hash
- アラビア語の文字列を含む
Hash
でキーを検索すると常にnil
が返ってくる、というバグ報告
foo = {"arabic" => "ٱلتَّوْبَة"} p foo.keys # => ["arabic"] p foo["arabic"] # => nil p foo.values_at("arabic") => [nil] foo.fetch "arabic" # Raises error with - did you mean "arabic" ?
- どうして…、と思ったら上記の再現コードのキーに
U200e
が紛れているのが原因だったらしいU200e
は Left-to-Right Mark (LRM) と呼ばれる制御文字
- 実際に Vim でコードを貼り付けるとこんな感じ
- 制御文字を取り除いたら問題なく動作した
foo = {"arabic" => "ٱلتَّوْبَة"} p foo.keys # => ["arabic"] p foo["arabic"] # => "ٱلتَّوْبَة" p foo.values_at("arabic") => {["ٱلتَّوْبَة"]=>[nil]}
[Feature #18040] Why should foo(1 if true)
be an error?
foo(1 if true)
がエラーになるのはなぜか?というバグ報告- パーサ的には
1 if true
は式ではなくてステートメントなので現状は意図する挙動だとコメントされている - その後は
1 if true
が式なのかステートメントなのかで議論が続いている - 最終的には『現実的に修正できない』という理由で Reject されている
- ちなみに
p foo((1 if true))
みたいに()
でくくると動作する
[Feature #15211] Integer.try_convert
Integer.try_convert
を追加する提案Array.try_convert
やRegexp.try_convert
などは既にある- 任意のオブジェクトを自身に変換するメソッド
Regexp.try_convert(/re/) # => /re/ # 失敗したら nil を返す Regexp.try_convert("re") # => nil
Integer.try_convert
は最新版では実装済み
p Integer.try_convert(10) # => 10 p Integer.try_convert("10") # => nil # ちなみに内部で to_int を呼び出しているので Float だとこうなる p Integer.try_convert(1.23) # => 1
[Feature #18008] keyword_init?
method for Struct
Struct.new
でkeyword_init: true
したかどうかを判定するメソッドを追加する提案- 次のように
Struct.new
の戻り値に対して判定できる
S1 = Struct.new(:a, :b) S2 = Struct.new(:a, :b, keyword_init: true) S3 = Struct.new(:a, :b, keyword_init: false) # 指定しなかった場合は nil を返す pp S1.keyword_init? # => nil pp S2.keyword_init? # => true pp S3.keyword_init? # => false
- これは既に最新版で対応済み
[Feature #17724] Make the pin operator support instance/class/global variables
- 元々はパターンマッチで
^@n
を使用すると『ローカル変数かメソッドを期待する』とエラーメッセージになっていた
# ローカル変数かメソッドを期待する、というエラーメッセージが出力される case 10 in ^@n end # => error: syntax error, unexpected instance variable, expecting local variable or method # in ^@n # ^~
- しかし、メソッドの場合でもエラーになるのでエラーメッセージを修正しよう、という内容のチケットだった
def n = 10 # メソッドを使用してもエラーになる case 10 in ^n end # => error: n: no such local variable
- これの対応として
^
にインスタンス/クラス/グローバル変数
が使えるように対応された
class X @a = 1 @@b = 2 $c = 3 # インスタンス、クラス、グローバル変数が使える case 1 in ^@a in ^@@b in ^$c end end
- これは最新版で実装済み