⛳
[Feature #18368] Range#step の挙動を調整する提案
[Feature #18368] Range#step semantics for non-Numeric ranges
-
Range#step
の挙動を調整するチケット - 現状の実装だと「
#succ
で begin を N 回進めて、結果を返す」という挙動になっている - それを「begin + step で繰り返して結果を返す」という挙動に変えたいというのがチケットの内容
- 要は
Range#step
の挙動を調整し、以下のようなコードを動かせるようにするのがチケットの目的
# 1日ずつ加算して配列に変換したい
# いまはこれができない
(Time.parse('2021-12-01')..Time.parse('2021-12-24')).step(1.day).to_a
- 最終的には互換性を保ちつつ
+
でも繰り返すようにされる予定
# 以下のようなコードが動くようになる
p ('a'..).step('a').take(3)
# => ["a", "aa", "aaa"]
p (Time.now..).step(24*60*60).take(3)
# => [2023-03-04 12:16:52.546531817 +0200,
# 2023-03-05 12:16:52.546531817 +0200,
# 2023-03-06 12:16:52.546531817 +0200]
- また、いくつか挙動が調整されており、以下のように
#step
に負の値 + ブロックを渡したときにエラーにならなくなりました
# これは Ruby 3.3 でも PR でも変わらない
p (1..-10).step(-3).to_a
# => [1, -2, -5, -8]
# これは元々エラーになっていたが動くようになる
(1..-10).step(-3) { p _1 }
# Ruby 3.3 => step can't be negative (ArgumentError) -- inconsistent with ArithmeticSequence behavior
# PR => 1, -2, -5, -8
- また、以下のように float が絡む場合の挙動も変わる
require 'active_support/all'
p (1.0..).step(2.minutes).take(3)
# Ruby 3.3 => [1.0, 121.0, 241.0] -- これは内部で #to_f が呼ばれて、その値が加算される
# PR => [1.0, 2 minutes and 1.0 second, 4 minutes and 1.0 second] -- これは #coerce で適切に変換されるようになった
- 上記であげたように実装自体はされており、いまは PR のレビュー中って感じですね
Discussion