Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#between? error or anomaly in Cooper's *Beginning Ruby*

Tags:

ruby

In Cooper's book Beginning Ruby, page 166 there's an example I'm unable to reproduce.

class Song
  include Comparable

  attr_accessor :length
  def <=>(other)
    @length <=> other.length
  end

  def initialize(song_name, length)
    @song_name = song_name
    @length = length
  end
end

a = Song.new('Rock around the clock', 143)
b = Song.new('Bohemian Rhapsody', 544)
c = Song.new('Minute Waltz', 60)

a.between?(b, c)

In the book, it says the result should be => true while I'm getting => false.

I went on to break it down to...

puts 143.between?(544, 60) # => false
puts 143.between?(60, 544) # => true

And according to ruby-doc.org, it's supposed to be written as between?(min,max) -- which leads me to believe

  • a) the book has a mistake
  • b) in an earlier version of Ruby, between? was more flexible and allowed (max,min)
  • c) this example is somehow anomalous and I'm missing something

Which is it?

like image 722
stephen Avatar asked Nov 27 '15 17:11

stephen


3 Answers

After a quick investigation, it looks like it's just a mistake in the book (if you are quoting it correctly).

I found the book as pdf here. Unfortunately, page 166 is missing. However, on page 5, it says:

In the "Ruby on Windows" section, you'll see a few links for different versions of Ruby you can download for Windows. Ideally you want to download the file at the link that's highest in the list that's referred to as a "One-Click Installer." At the time of writing, this version is 1.8.5.

Checking CRuby's 1.8.5 Comparable implementation, you can clearly see that between? works the way it does today.

like image 169
ndnenkov Avatar answered Nov 18 '22 06:11

ndnenkov


This has been covered in some comments above, but as the author of the book I wanted to clarify that the 2009 edition (edition 2) of the book had this issue corrected. The original poster has updated that they were reading the 2007 edition :-)

As a definitive answer to the question, however, yes, the first edition of the book was in error.

like image 39
Peter Cooper Avatar answered Nov 18 '22 06:11

Peter Cooper


I just wanted to show you this. This is the C-source for the between? method:

               static VALUE
cmp_between(VALUE x, VALUE min, VALUE max)
{
    if (RTEST(cmp_lt(x, min))) return Qfalse;
    if (RTEST(cmp_gt(x, max))) return Qfalse;
    return Qtrue;
}

While I didn't look at every single version, I believe this method has remained unchanged since Ruby 1.8.7.

The cmp_lt and cmp_gt in plain english are "compare less than" and "compare greater than".

So as you can see, the method will return false if the value x, which in your case would be your a objects length of 144, is less than the min, which would be b's length of 544. Since 144 < 544, you're getting the correct answer, and it does appear that the book contains a mistake.

I can't seem to determine whether this error has ever been reported before, so if you're inclined, it might be good to contact the author and let him know.

like image 2
Paul Richter Avatar answered Nov 18 '22 06:11

Paul Richter