[ruby-list:49798] Re: Range class?
From:
"Masa" <imagine@...>
Date:
2014-04-20 15:52:06 UTC
List:
ruby-list #49798
まつもとさま、皆様
坂野正明です。
まつもとさん、早速のそして大変明快なご返事を
ありがとうございました!
お蔭様で多くの疑問が解けました!
一点、Range の要素が Rational と Floatで違いがでるのが
まだ分かりませんが……(後述します)。
以下、それぞれご返事を書きます。
2014年 4月 20日(日)10:58 pm に Yukihiro Matsumoto さんは書きました:
> まつもと ゆきひろです
>
> Rangeの奇妙な振る舞いを理解するためには、Rangeのメソッドには、
> Enumerableとして振る舞うものと、Intervalとして振る舞うものの
> の両方があることに注意しなければなりません。
>
> Enumerableとして振る舞うものは離散的で、eachメソッドが生成す
> る要素を使います。Rangeの場合、eachは始点から1.0ずつ離れた値
> が生成されます(数値の場合)。
そうだったのですか!
始点から 1.0 (Float?)というステップだったとは
存じませんでした。
たとえば、
irb> (1.0..5).each {|n| print n, ' ' }
TypeError: can't iterate from Float
from (irb):30:in `each'
というように、始点が Float であればそもそも
Exception が発生します。
だから、例外無しに succ() が使われていると
思い込んでいたものでした……。
# 内部の実装として、数値の場合は数値計算した方が
# 速いだろうとは(言われてみれば)想像できますが。
> Intervalとして振る舞うものは連続的で始点(begin)と終点(end)の
> 大きさで決まります。
>
> たとえば、include?はeachを使い、cover?は始点と終点の間の比較
> で判定します。
はい、分かります。
first と begin との違いも同様ですよね。その場合は
数値を例外として。
> ですから、ご指摘のメソッドではこのような事情があります。
>
> maxは終点を、minmaxは最終要素を返します。
> sizeはeachの与える要素数を返します。
>
> 例として「0.5...5」は「0.5から1.0刻みで5.0を越えない要素の数」
> という意味になり、それらの要素は[0.5, 1.5, 2.5, 3.5, 4.5]です
> から「(0.5...5).size」は5になります。
>
> 理解(or 納得)の一助になりましたでしょうか?
明快です。
ありがとうございました。
四捨五入か何かと疑うことになったのは、偶然、私が
使った例の始点が 1.5 という値だったからというだけですね。
参りました。
一点だけ、まだそれでは説明できないのは、以下の例です。
| irb> (Rational(1,2)...5).size # => 4
| irb> (0.5...5).size # => 5 # Why not 4??
Rational の方が(だけ?)整数化されているように、
もしくはそれを下回らない最小の整数になっているような
挙動ですね。
上の違い、特に max/minmax の方は、マニュアルに書かれて
あれば親切かも知れませんね。
# 現実的に問題になることは相当稀でしょうが……。
include?/cover? や first/begin と違って(←これらは、
最初に理解した時に、命名の見事さに感動したものでした!
短い名にして体をよく表している、と)、挙動に違いがある
ことが予想あるいは理解しにくいと恐れますもので。
坂野正明