Project

General

Profile

Actions

Bug #14845

closed

Endless Range with nil

Added by igaiga (Kuniaki Igarashi) over 6 years ago. Updated over 6 years ago.

Status:
Closed
Target version:
-
ruby -v:
2.6.0preview2
[ruby-dev:50568]

Description

endless Rangeで次のケースで困ることがあります。

  • 1..nilはendless Rangeになる
  • endless Rangeはto_aすると返ってこなくなる
  • 1..変数 のケースで意図せずendless Rangeになる可能性があり、そのときto_aすると返ってこなくなる

Ruby 2.5.1 では 1..nil はArgumentError (bad value for range) になります。

たとえば、 1..nil がendless Rangeではなくエラーになればこの問題は解決します。

Info


Files

range_to_a.patch (1.56 KB) range_to_a.patch mame (Yusuke Endoh), 06/13/2018 11:19 AM

Related issues 1 (1 open0 closed)

Related to Ruby master - Misc #17637: Endless ranges with `nil` boundary weird behaviorOpenActions

Updated by mame (Yusuke Endoh) over 6 years ago

現状の挙動はそれはそれで便利そう※なので、early failure と便利さとのトレードオフです。どっちがいいでしょうね。

※たとえば SQL の DSL で count: (min..max) という Range を書いたとき、max = nil にするだけで「上限なし」を表現できるという使い方が考えられます。(1..nil) がエラーになると、count: max ? (min..max) : (min..) とかいう記述が必要になり、DSL としては終了です。

問題を to_a に限れば、(1..nil).to_aenum.cycle.to_a のように、明らかに停止しない to_a 呼び出しを例外にするという解決もありえると思います(「明らかに停止しない」が本当に正しいかどうか自信が持てないところですが)。

うっかり (1..nil) を作ってしまったというリアルな例などがあると、議論が捗りそうです。

Actions #2

Updated by mame (Yusuke Endoh) over 6 years ago

  • Status changed from Open to Closed

Applied in changeset trunk|r63646.


range.c: prohibit (1..nil)

Now endless range can be created by either a literal (1..) or explicit
range creation Range.new(1, nil). [Bug #14845]

This change is intended for "early failure"; for example,
(1..var).to_a causes out of memory if var is inadvertently nil.

Updated by mame (Yusuke Endoh) over 6 years ago

  • Status changed from Closed to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)

https://twitter.com/yukihiro_matz/status/1006737384820445184

いやあ、エラーではねた方がいいんじゃないですかね。

ていうのがあったので、とりあえず r63646 で (1..nil) を禁止しました。ただし Range.new(1, nil) は許しています(そうしないと Range のサブクラスを endless にする手段がないので)。

個人的には、DSL が終了してしまったのと、無駄に複雑になった気がして、あんまり好きじゃないです。次の開発者会議で相談させてください。

Actions #4

Updated by mame (Yusuke Endoh) over 6 years ago

  • Status changed from Assigned to Closed

Applied in changeset commit:ruby-git|48de2ea5f9b9067779acb0f7f76e5f879f2b42c0.


range.c: prohibit (1..nil)

Now endless range can be created by either a literal (1..) or explicit
range creation Range.new(1, nil). [Bug #14845]

This change is intended for "early failure"; for example,
(1..var).to_a causes out of memory if var is inadvertently nil.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Updated by matz (Yukihiro Matsumoto) over 6 years ago

I meant (1..).to_a to raise an exception (for apparent infinity loop), not prohibiting 1..nil'.

Matz.

Updated by mame (Yusuke Endoh) over 6 years ago

  • Status changed from Closed to Assigned

matz (Yukihiro Matsumoto) wrote:

I meant (1..).to_a to raise an exception (for apparent infinity loop), not prohibiting 1..nil'.

Matz.

Sorry for my misunderstanding. I reverted r63646.

Updated by mame (Yusuke Endoh) over 6 years ago

I'm attaching a patch for Range#to_a that raises an RangeError for an endless range, and that calls super to Enumerable#to_a for a normal range.

Updated by znz (Kazuhiro NISHIYAMA) over 6 years ago

別チケットにした方が良いのかもしれませんが、関連するのでここにコメントしておきます。

Range.new(1) のように終端を省略できるようにするのはどうでしょうか?
endless range の時は exclude_end を指定できても違いがないようなので、現状では問題がなさそうに思います。

beginless などの可能性を考えるとキーワード引数も受け付けるようにして、 Range.new(begin: 1, endless: true)Range.new(begin: 1, end: 9, exclude_end: true) のようにかけると良いかもしれません。

Actions #9

Updated by mame (Yusuke Endoh) over 6 years ago

  • Status changed from Assigned to Closed

Applied in changeset trunk|r63714.


range.c: Range#to_a now raises RangeError if it is endless

Fixes [Bug #14845]

Actions #10

Updated by mame (Yusuke Endoh) over 3 years ago

  • Related to Misc #17637: Endless ranges with `nil` boundary weird behavior added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0