👻

[Feature #20080] Introduce #bounds method on Range

2024/01/12に公開

[Feature #20080] Introduce #bounds method on Range

  • Range#begin, end を返す Range#bounds メソッドを追加する提案
# [begin, end] の配列を返す
first, last = (1..300).bounds # => [1, 300]
first, last = (300..1).bounds # => [300, 1]
first, last = (..300).bounds # => [nil, 300]
first, last = (1..).bounds # => [1, nil]
  • また Range#exclude_end?true の場合はその情報が第三要素で受け取る事ができる
    • これを利用してシリアライズ化が簡単にできるようになる
# ... の場合は第三要素に true が渡される
a = (1..2).bounds  #=> [1,2]
b = (1...2).bounds #=> [1,2,true]

# これを利用すると bounds の結果から元の Range を簡単に復元する事ができる
Range.new(*a)      #=> 1..2
Range.new(*b)      #=> 1...2
  • この Range#exclude_end? 値を含めるか含めないかは Range#bounds の引数で制御することができる
# true を渡すと Range#exclude_end? の結果に変わらずに含める
(1..2).bounds(true)  #=> [1,2,false]
(1...2).bounds(true)  #=> [1,2,true]

# false を渡すと Range#exclude_end? の結果に変わらずに含めない
(1..2).bounds(false)  #=> [1,2]
(1...2).bounds(false)  #=> [1,2]
  • このチケットの背景は Feature #20027: Add Range DeconstructionRange を分割代入したい、っていう要望からの派生ですね
  • 上記のチケットだと Range を直接分割代入するのは Reject されたんですが、その代わりにメソッドを追加する案があったのでそれの派生になります
  • Range#minmax と似ているんですが #minmax の場合は begin > end の場合に nil を返したりするのでちょっとだけ挙動が異なります
(1..42).minmax #=> [1, 42]
(42..1).minmax #=> [nil, nil]
  • まあ普通に便利そうな感じはしますねー
GitHubで編集を提案

Discussion