Project

General

Profile

Bug #14845

Endless Range with nil

Added by igaiga (Kuniaki IGARASHI) 11 days ago. Updated 2 days ago.

Status:
Closed
Priority:
Normal
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

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

Associated revisions

Revision 48de2ea5
Added by mame (Yusuke Endoh) 11 days ago

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

Revision 63646
Added by mame (Yusuke Endoh) 11 days ago

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.

Revision 606d6b34
Added by mame (Yusuke Endoh) 11 days ago

Revert "range.c: prohibit (1..nil)"

This reverts commit a44c010764a16ae09aaed49d76eec055ca0057c8.
Refs #14845.

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

Revision 63649
Added by mame (Yusuke Endoh) 11 days ago

Revert "range.c: prohibit (1..nil)"

This reverts commit a44c010764a16ae09aaed49d76eec055ca0057c8.
Refs #14845.

Revision c19ecf05
Added by mame (Yusuke Endoh) 2 days ago

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

Fixes [Bug #14845]

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

Revision 63714
Added by mame (Yusuke Endoh) 2 days ago

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

Fixes [Bug #14845]

History

#1 [ruby-dev:50569] Updated by mame (Yusuke Endoh) 11 days 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) を作ってしまったというリアルな例などがあると、議論が捗りそうです。

#2 Updated by mame (Yusuke Endoh) 11 days 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.

#3 [ruby-dev:50570] Updated by mame (Yusuke Endoh) 11 days ago

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

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

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

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

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

#4 Updated by mame (Yusuke Endoh) 11 days ago

  • Status changed from Assigned to Closed

Applied in changeset 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

#5 [ruby-dev:50571] Updated by matz (Yukihiro Matsumoto) 11 days ago

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

Matz.

#6 [ruby-dev:50572] Updated by mame (Yusuke Endoh) 11 days 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.

#7 [ruby-dev:50573] Updated by mame (Yusuke Endoh) 11 days 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.

#8 [ruby-dev:50574] Updated by znz (Kazuhiro NISHIYAMA) 10 days ago

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

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

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

#9 Updated by mame (Yusuke Endoh) 2 days 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]

Also available in: Atom PDF