Project

General

Profile

Actions

Bug #4577

closed

(int...float).max should not raise an error

Added by yimutang (Joey Zhou) about 13 years ago. Updated over 11 years ago.

Status:
Rejected
Target version:
-
ruby -v:
-
Backport:
[ruby-core:35754]

Description

=begin
(int...float).max (without a block) will raise an error:

(({p (1...9.3).max # cannot exclude non Integer end value (TypeError)}))

I don't think it should do so.

int...float is a valid range object. When I construct such range, there's no error message.

The range can call all the Range instance methods. Only when calling single #max, the errmsg seems to tell that the range itself is not valid.

#max with a block will not raise the error:

(({p (1...9.3).max {|a,b| a <=> b} #=> 9}))

I think (1...9.3).max should also return 9( (end_obj-1).ceil ). If you admit the legality of #max(&block), you should also admit #max().
=end


Related issues 2 (0 open2 closed)

Related to Ruby master - Bug #4591: (1.5...2).max #=> 1 (Range#max)Closedtarui (Masaya Tarui)04/21/2011Actions
Related to Ruby master - Bug #974: Range#max で終了しないことがあるClosed01/04/2009Actions

Updated by tarui (Masaya Tarui) about 13 years ago

  • ruby -v changed from ruby 1.9.2p180 (2011-02-18) [i386-mingw32] to -

=begin
Hi,

I feel that 1.8's Range#max is good.

1.9's Range#max sometimes does strange behavior.

irb
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 1.9.3dev (2011-04-11 trunk 31261) [i386-mswin32_100]"
irb(main):002:0> (1..1.2).max
=> 1.2
irb(main):003:0> (1...1.2).max
TypeError: cannot exclude non Integer end value
irb(main):004:0> (1.1..3.2).max
=> 3.2
irb(main):005:0> (1.1..2).max
=> 2
irb(main):006:0> (1.1...2).max
=> 1

(1.1...2).max is 1 ?!!!
I cannot think it is correct result.

Here is 1.8's

irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 1.8.7 (2010-01-10 patchlevel 249) [i386-mingw32]"
irb(main):002:0> (1..1.2).max
=> 1
irb(main):003:0> (1...1.2).max
=> 1
irb(main):004:0> (1.1..3.2).max
TypeError: can't iterate from Float
irb(main):005:0> (1.1..2).max
TypeError: can't iterate from Float
irb(main):006:0> (1.1...2).max
TypeError: can't iterate from Float

Here is better though it is sad not to be able to treat Float.

btw, I have used Range only with Integer :-)

Masaya TARUI
No Tool,No Life.
=end

Updated by matz (Yukihiro Matsumoto) about 13 years ago

=begin
Hi,

In message "Re: [ruby-core:35754] [Ruby 1.9 - Bug #4577][Open] (int...float).max should not raise an error"

on Fri, 15 Apr 2011 00:02:07 +0900, writes:
Bug #4577: (int...float).max should not raise an error
http://redmine.ruby-lang.org/issues/4577

|(int...float).max (without a block) will raise an error:
|
|(({p (1...9.3).max # cannot exclude non Integer end value (TypeError)}))
|
|I don't think it should do so.

OK, you don't think it should do so, then what do you think it should
do? ... makes ranges excludes the end point. When the end point is
floating point number, what should be the max value of the range, that
should be less than (and not equals to) the end point?

I don't think ((end_obj-1).ceil) is not the best value for #max, since
we don't define excluding end point by ((end_obj-1).ceil). yet, at
least.

						matz.

=end

Updated by yimutang (Joey Zhou) about 13 years ago

=begin
Well, what I mean is ((#max without block)) and ((#max {block})) should act the same way, maybe.

(1...6.3).max {|a,b| a <=> b} # 6

Why this one can iterate from 1 to 6, but not single #max ?

It seems there are two #max, one support #each, and another not.

I think this results in confusion.

Here:

p (1..6.3).last # 6.3, same as (1..6.3).end
p (1..6.3).last(1) # [6]
p (1...6.3).last(1) # [6], well... not [6.3]

two dots, or three dots, return the same array, with the element an int number.

thus #last(n) can return int number, although its end_obj is floating point number,
I think (1...6.3).max returning int 6 is also OK. it can be a rule.

I think the methods' behaviour of Range class should be consistent, when the range contains floating point number.

Joey
=end

Updated by yimutang (Joey Zhou) about 13 years ago

=begin
Ranges with numbers as begin_obj and end_obj can be summarized to four(..and...):

int..int # no problem
float..float # no problem, float has no #succ, cannot iterate
float..int # act as float..float, no problem, no #succ, no iteration
int..float # I think more attention should be paid to this...

I suggest the feature here:

when int..float is used in #cover? #include? #===, there's no problem, just: begin_obj <=> obj and obj <=> end_obj

but when int..float(and int...float) is used in any method requiring iteration, the fractional part of float, may be dropped as scrap, if needed.

(1..5.3).to_a #=> [1,2,3,4,5]
(1..5.0).to_a #=> [1,2,3,4,5]
(1...5.3).to_a #=> [1,2,3,4,5]
(1...5.0).to_a #=> [1,2,3,4]
(1..5.3).last(1) #=> [5]
(1...5.3).last(1) #=> [5]

the methods above are all OK, you can say there's a implicit rule: "0.3 is scrap, we dropped it"

but #last and #max:

(1..5.3).last #=> 5.3
(1...5.3).last #=> 5.3
(1..5.3).max #=> 5.3, well, same as #end
hmm, #end, #last(no arg), #max(no block) all act the same, why should we need three methods to tell the end_obj?
(1...5.3).max # ERROR!

(1..5.3).max {|a,b| a <=> b} # 5, fraction-scrap
(1...5.3).max {|a,b| a <=> b} # 5 too

If the single #max follow "fraction-scrap" rule, I think it's better
(1..5.3).max #=> 5
(1...5.3).max #=> 5
(1...5.0).max #=> 4
=end

Updated by ko1 (Koichi Sasada) almost 13 years ago

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

Updated by matz (Yukihiro Matsumoto) almost 12 years ago

  • Status changed from Assigned to Rejected

After the discussion with core team members, I see no valid reason to make a change, except for vague feeling.
So I reject it at the moment.

Matz.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0