Bug #974
closedRange#max で終了しないことがある
Description
=begin
以下のようにすると終了しないようです。
$ ./ruby -e 'inf=1.0/0; (0...inf).max'
=end
Updated by matz (Yukihiro Matsumoto) almost 16 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:37688] [Bug #974] Range#max で終了しないことがある"
on Sun, 4 Jan 2009 02:05:40 +0900, tadayoshi funaba redmine@ruby-lang.org writes:
|以下のようにすると終了しないようです。
|
|$ ./ruby -e 'inf=1.0/0; (0...inf).max'
実装としては
(b...e)とした場合、eが整数でなければ、bからeまで繰り返して、
最後に繰り返した(かつeに等しくない)値を返す
という動作をしています。「...」の場合、最大値はeそのものでは
なく、Rangeを繰り返した結果eを越えない最大値なので、確実にわ
かる手段は実際に繰り返すことだからですが、その結果、eに無限大
を指定すると終了しないわけ(いや、いつかは終了するのかな)です。
これはある意味、終了しないのが指定した通りの動作であると言え
ないこともありません。
終了するべきでないとすると、それに合わせて新たな「仕様」を定
義する必要がありますが、どのような仕様が適切か正直よくわかり
ませんね。
- eがFloatかつ無限であればそれを返す(...の定義に反するような)
- eがFloatかつ無限であればエラー
- その他
うーむ。数に関する知識を利用して、より賢い動作をさせてあげた
いものですが。
=end
Updated by tadf (tadayoshi funaba) almost 16 years ago
=begin
終了するべきでないとすると、それに合わせて新たな「仕様」を定
義する必要がありますが、どのような仕様が適切か正直よくわかり
ませんね。
- eがFloatかつ無限であればそれを返す(...の定義に反するような)
- eがFloatかつ無限であればエラー
- その他
エラーにしてもいいような気がしています。許しても延々と資源を消費するだ
けじゃないですか。
(0..1).step(0){} のようなものは現状ではエラーになるけど、これは許しても
むしろ利用者が理解できるものになると思います。
ところで
(0...3).last #=> 3
この場合の last というのも変な感じがしますね。
=end
Updated by matz (Yukihiro Matsumoto) almost 16 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:37690] Re: [Bug #974] Range#max で終了しないことがある"
on Sun, 4 Jan 2009 07:00:25 +0900, Tadayoshi Funaba tadf@dotrb.org writes:
|> * eがFloatかつ無限であればそれを返す(...の定義に反するような)
|> * eがFloatかつ無限であればエラー
|> * その他
|
|エラーにしてもいいような気がしています。許しても延々と資源を消費するだ
|けじゃないですか。
eがNumericでIntegerでない時、...のmaxはエラーにすることにし
ました。末尾を含まない最大値が定義できないので。
|ところで
|
|(0...3).last #=> 3
|
|この場合の last というのも変な感じがしますね。
そうですね。lastをRangeが「生成する列の最後の値」ではなく、区
間指定の最後(後ろの方)だとむりやり解釈してください。
=end
Updated by matz (Yukihiro Matsumoto) almost 16 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
=begin
Applied in changeset r21327.
=end
Updated by yugui (Yuki Sonoda) almost 16 years ago
=begin
Yuguiです。
On 1/5/09 6:38 AM, Yukihiro Matsumoto wrote:
eがNumericでIntegerでない時、...のmaxはエラーにすることにし
ました。末尾を含まない最大値が定義できないので。
当面これをエラーにすることには賛成ですが、理由が違うと思います。
先頭sと末尾eで定義されるところの{n <- N | s <= n < e} なる集合に最大値が
存在することはまったく問題ないわけです。
問題は、上に開いた区間の最大値を定義するために適切な距離関数を与えねばな
らないところ、両端が整数であればsuccの"移動距離"で定まる離散的な距離を与
えてやるのが適切であると推測されるのに対して、整数と非整数の組み合わせで
はそれが曖昧だと言うことです。
この曖昧さに対して、浮動小数点同士の開いた範囲の場合に倣って例外を発生す
ることは当面適切だと思います。しかしながら、将来的にsuccに似たメソッドを
シンボルで指定してやる形式は検討の余地があるかと思いました。
Class Float
def step_0_5
self + 0.5
end
end
(1.0...3.0).max(:step_0_5) #=> 2.5
この検討の是非はともかく、この変更の理由については明確にしておく必要があ
ると思いましてpostしました。
なお、バグとは言いづらいので、時期的な問題からこの変更は1.9.1には取り込
みません。
--
Yugui yugui@yugui.jp
http://yugui.jp
私は私をDumpする
=end
Updated by matz (Yukihiro Matsumoto) almost 16 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:37720] Re: [Bug #974] Range#max で終了しないことがある"
on Wed, 7 Jan 2009 19:39:55 +0900, "Yugui (Yuki Sonoda)" yugui@yugui.jp writes:
|> eがNumericでIntegerでない時、...のmaxはエラーにすることにし
|> ました。末尾を含まない最大値が定義できないので。
|
|当面これをエラーにすることには賛成ですが、理由が違うと思います。
|
|先頭sと末尾eで定義されるところの{n <- N | s <= n < e} なる集合に最大値が
|存在することはまったく問題ないわけです。
|問題は、上に開いた区間の最大値を定義するために適切な距離関数を与えねばな
|らないところ、両端が整数であればsuccの"移動距離"で定まる離散的な距離を与
|えてやるのが適切であると推測されるのに対して、整数と非整数の組み合わせで
|はそれが曖昧だと言うことです。
「定義できない」という用語の使い方が不適切だったのかもしれま
せん。言いたかったのは、範囲[a,b)について、bが浮動小数点数で
あった場合、
- 万人が納得する (万人じゃなくて多くが、でもいいけど)
- かつ有用な
最大値の唯一の定義は存在しなさそうだ、ということです。「シン
ボルで指定する」というYuguiさんの提案は「唯一がなければ指定
してやればいいじゃないか」ということなのだと思いますが、それ
であればブロックを指定すればよいような(現状はブロックを指定
しても始点がFloatだと動きませんが)。
|なお、バグとは言いづらいので、時期的な問題からこの変更は1.9.1には取り込
|みません。
これについては同意します。
まつもと ゆきひろ /:|)
=end