Nuby - why does my #inspect misbehave?

I'm working through a few exercises to teach myself Ruby. One of them is the creation of a deck of cards along with all the usual operations one performs upon them.

I override the Object#inspect method to pretty-print my card values, but it doesn't always get called. Whether or not it gets called depends on the **absence** of a line in #print_playing_deck. Here is my code stripped down to the basics.

class Card < Object
   attr_reader :suit, :value

   protected
   attr_writer :suit, :value

   public
   def initialize(suit = "Joker", value = 15)
     @suit = suit
     @value = value
   end

   def inspect
       puts "#{self.value} of #{self.suit}s"
   end
end

class CardDeck < Card
   attr_reader :size

   SUITSIZE = 13

   def initialize(size = 52)
     @size = size

     @playing_deck = Array.new(@size) do |index|
       case index
       when *(0..12)
         Card.new("Heart", index + 1)
       end
     end
     @number_remaining = @playing_deck.length
   end

   def print_playing_deck
     @playing_deck.each do |card|
       puts card
     end
     # WEIRD!! If I have any code after this loop, my Card#inspect is not called.
     # In this case I have a "puts" but it could even be arithmetic expressions preventing
     # the #inspect from working
     #puts "#{@playing_deck.length} cards in deck"
   end

end

And here is the output:

irb(main):001:0> load 'ex.rb'
=> true
irb(main):002:0> d=CardDeck.new(5)
of s
=>
irb(main):003:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
5 cards in deck
=> nil
######## comment out the "puts" in #print_playing_deck and reload
irb(main):004:0> load 'ex.rb'
./ex.rb:22: warning: already initialized constant SUITSIZE
=> true
irb(main):005:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
1 of Hearts
2 of Hearts
3 of Hearts
4 of Hearts
5 of Hearts
=> [, , , , ]

I don't understand why my Card#inspect method doesn't print anything to stdout when there is code after the loop. Is this just a weird artifact of irb?

BTW, running on OSX with darwinports Ruby 1.8.4.

As a general rule #inspect is not supposed to print anything it is supposed to return a string. Likewise in this case I believe your inspect method is better named "to_s" since it gets you a string representation of the object, not a peek into the objects internal state. I don't know what the cause of your bug is though. Irb will usually print the inspect string of an evaluated expression on its own though, and puts returns nil. So when irb does the equivalent of p a_card its going to get back nil which is gonna be converted to the empty string. This may be part of your problem, but first I would suggest changing your code to match the usual ruby conventions and secondly try running the code outside of irb.

···

On Mar 2, 2006, at 8:30 PM, cremes.devlist@mac.com wrote:

I'm working through a few exercises to teach myself Ruby. One of them is the creation of a deck of cards along with all the usual operations one performs upon them.

I override the Object#inspect method to pretty-print my card values, but it doesn't always get called. Whether or not it gets called depends on the **absence** of a line in #print_playing_deck. Here is my code stripped down to the basics.

class Card < Object
  attr_reader :suit, :value

  protected
  attr_writer :suit, :value

  public
  def initialize(suit = "Joker", value = 15)
    @suit = suit
    @value = value
  end

  def inspect
      puts "#{self.value} of #{self.suit}s"
  end
end

class CardDeck < Card
  attr_reader :size

  SUITSIZE = 13

  def initialize(size = 52)
    @size = size

    @playing_deck = Array.new(@size) do |index|
      case index
      when *(0..12)
        Card.new("Heart", index + 1)
      end
    end
    @number_remaining = @playing_deck.length
  end

  def print_playing_deck
    @playing_deck.each do |card|
      puts card
    end
    # WEIRD!! If I have any code after this loop, my Card#inspect is not called.
    # In this case I have a "puts" but it could even be arithmetic expressions preventing
    # the #inspect from working
    #puts "#{@playing_deck.length} cards in deck"
  end

end

And here is the output:

irb(main):001:0> load 'ex.rb'
=> true
irb(main):002:0> d=CardDeck.new(5)
of s
=>
irb(main):003:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
5 cards in deck
=> nil
######## comment out the "puts" in #print_playing_deck and reload
irb(main):004:0> load 'ex.rb'
./ex.rb:22: warning: already initialized constant SUITSIZE
=> true
irb(main):005:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
1 of Hearts
2 of Hearts
3 of Hearts
4 of Hearts
5 of Hearts
=> [, , , , ]

I don't understand why my Card#inspect method doesn't print anything to stdout when there is code after the loop. Is this just a weird artifact of irb?

BTW, running on OSX with darwinports Ruby 1.8.4.

Hi --

I'm working through a few exercises to teach myself Ruby. One of them is the creation of a deck of cards along with all the usual operations one performs upon them.

I override the Object#inspect method to pretty-print my card values, but it doesn't always get called. Whether or not it gets called depends on the **absence** of a line in #print_playing_deck. Here is my code stripped down to the basics.

class Card < Object

Don't inherit from Object -- it happens automatically :slight_smile:

def inspect
    puts "#{self.value} of #{self.suit}s"
end

This is having a weird effect on what you get in irb, like when you
create a deck, you get:

   of s

because it's trying to print that string. #inspect should really just
return a string, not print it out (as I think Logan also mentioned).

def print_playing_deck
  @playing_deck.each do |card|
    puts card
  end

One of the great rites of passage for new Rubyists is learning that:

   puts array

does the iterating for you :slight_smile: So that should be just:

   puts @playing_deck

  # WEIRD!! If I have any code after this loop, my Card#inspect is not called.
  # In this case I have a "puts" but it could even be arithmetic expressions preventing
  # the #inspect from working
  #puts "#{@playing_deck.length} cards in deck"
end

And here is the output:

irb(main):001:0> load 'ex.rb'
=> true
irb(main):002:0> d=CardDeck.new(5)
of s
=>
irb(main):003:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
5 cards in deck
=> nil

That nil is the return value of puts, which is the last expression in
#print_playing_deck.

######## comment out the "puts" in #print_playing_deck and reload
irb(main):004:0> load 'ex.rb'
./ex.rb:22: warning: already initialized constant SUITSIZE
=> true
irb(main):005:0> d.print_playing_deck
#<Card:0x65b4>
#<Card:0x63e8>
#<Card:0x62a8>
#<Card:0x61cc>
#<Card:0x6168>
1 of Hearts
2 of Hearts
3 of Hearts
4 of Hearts
5 of Hearts
=> [, , , , ]

Now the last expression in #print_playing is @playing_deck (the return
value of the call to #each). To display @playing_deck, irb calls
#inspect on each element. The side-effect of this is that "1 of
Hearts" etc. gets printed. The return value of #inspect, however, is
nil (the value of puts), which is why you get the weird little array
of nothings at the end.

David

···

On Fri, 3 Mar 2006, cremes.devlist@mac.com wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

dblack@wobblini.net wrote:

One of the great rites of passage for new Rubyists is learning that:

  puts array

does the iterating for you :slight_smile:

:frowning:

···

--
James Britt

"Programs must be written for people to read, and only incidentally
  for machines to execute."
   - H. Abelson and G. Sussman
   (in "The Structure and Interpretation of Computer Programs)

Hi --

···

On Fri, 3 Mar 2006, James Britt wrote:

dblack@wobblini.net wrote:

One of the great rites of passage for new Rubyists is learning that:

  puts array

does the iterating for you :slight_smile:

:frowning:

?

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

unknown wrote:

Hi --

:frowning:

?

O-('_' Q)

···

On Fri, 3 Mar 2006, James Britt wrote:

--
Posted via http://www.ruby-forum.com/\.

dblack@wobblini.net wrote:

Hi --

One of the great rites of passage for new Rubyists is learning that:

  puts array

does the iterating for you :slight_smile:

:frowning:

?

POGSFJ

(I'll refrain from invoking P*LS)

James

···

On Fri, 3 Mar 2006, James Britt wrote:

dblack@wobblini.net wrote: