Newbie Q - calling a method for an object in an .each block?

Hello All. Sorry if this is obvious, but I have looked over the list
(and pickax) and not been able to solve it.

I am trying to iterate over a collection of objects, calling a method
defined within each object.

I have a class Card, with a method 'show' defined.

I then create an array of these Card objects. For example:

hand = Array.new
ace = Card.new( some_parameters )
hand[0] = ace
hand.push(Card.new( some_other_parameters))

etc.

Now,

ace.show #works:

=>"Card: A of Spades
hand[0].show # works, calls the 'show' method, executed for the first
'card', the ace:
=>"Card: A of Spades"

But,

hand.each {|c| c.show} # dosn't produces the following, which looks to me like a dump of the array:

=>[#<Card:0x2647f8 @face="Up", @value=12, @suit="s">, #<Card:0x20e3e4
@face="Up", @value=0, @suit="d">]

I fear I am misunderstanding something fundamental here, as I thought
the block parameter c should get each element of the array in turn, and,
each element being an object, I could call the methods associated with
that object.

Thanks for any insight,

Will

···

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

william robb wrote:

[snip]

hand.each {|c| c.show} # dosn't produces the following, which looks to me like a dump of the array:

=>[#<Card:0x2647f8 @face="Up", @value=12, @suit="s">, #<Card:0x20e3e4 @face="Up", @value=0, @suit="d">]

I fear I am misunderstanding something fundamental here, as I thought the block parameter c should get each element of the array in turn, and, each element being an object, I could call the methods associated with that object.

Don't fear, your instincts are good. I doubt you're
missing anything fundamental, you've just got some
kind of (interesting) bug.

The bug would seem to be in the code you haven't
shown us. Can you post more?

Hal

It's working but #each returns the array and your #show method returns a string, it doesn't have any side effects. You may want to use map instead or use puts

e.g.:

hand.each { |c| puts c.show }

or hand.map { |c| c.show }

···

On Jul 8, 2006, at 12:53 AM, william robb wrote:

Hello All. Sorry if this is obvious, but I have looked over the list
(and pickax) and not been able to solve it.

I am trying to iterate over a collection of objects, calling a method
defined within each object.

I have a class Card, with a method 'show' defined.

I then create an array of these Card objects. For example:

hand = Array.new
ace = Card.new( some_parameters )
hand[0] = ace
hand.push(Card.new( some_other_parameters))

etc.

Now,

ace.show #works:

=>"Card: A of Spades
hand[0].show # works, calls the 'show' method, executed for the first
'card', the ace:
=>"Card: A of Spades"

But,

hand.each {|c| c.show} # dosn't produces the following, which looks to me like a dump of the array:

=>[#<Card:0x2647f8 @face="Up", @value=12, @suit="s">, #<Card:0x20e3e4
@face="Up", @value=0, @suit="d">]

I fear I am misunderstanding something fundamental here, as I thought
the block parameter c should get each element of the array in turn, and,
each element being an object, I could call the methods associated with
that object.

Thanks for any insight,

Will

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

Logan Capaldo wrote:

It's working but #each returns the array and your #show method
returns a string, it doesn't have any side effects. You may want to
use map instead or use puts

e.g.:

hand.each { |c| puts c.show }

or hand.map { |c| c.show }

Ah! These work. Thank You!

I do recall from pickax that #each returns the array. It must be, then,
with

hand.each { |c| c.show }

what I am seeing how irb displays an array. Does this mean that the
string returned by #show is produced, but nothing is telling it to
display so it sort of ... gets assigned to nothing, and dosn't display
in irb?

But, then, why doesn't the block with the puts call first display the
strings followed by the display of the array returned by #each?

Follwing is the code defining the class (the rest I am just testing in
irb) for hal fulton, who asked for it. This is my first every ruby
program so it may be ugly, and could probably be improved upon. Been
programming in procedural languages since fortran 77, so this OO stuff
is a bit mind bending. But ... I like it!

class Card

  attr_reader :suit, :value, :face

  def initialize(suit,value)
    raise(IndexError, "Card: Suite out of range: #{suit}") if suit !~
/[hcds]/
    @suit = suit
    raise(IndexError, "Card: Value out of range: #{value}" ) if not
((0..12) === value)
    @value = value
    @face = "Down"
  end

  def ssuit
    case
      when @suit == "h" then "Hearts"
      when @suit == "c" then "Clubs"
      when @suit == "d" then "Diamonds"
      when @suit == "s" then "Spades"
    end
  end

  def pips
    case @value
      when 0 .. 8 then " " + (@value+2).to_s + " "
      when 9 then " J "
      when 10 then " Q "
      when 11 then " K "
      when 12 then " A "
    end
  end

  def show
    if @face == "Down"
      "Card: xxx xx xxxxx"
    else
      "Card: #{pips} of #{ssuit}"
    end
  end

  def flip
    if @face == "Down"
     then @face = "Up"
     else @face = "Down"
    end
  end

end

···

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

Logan Capaldo wrote:
>
> It's working but #each returns the array and your #show method
> returns a string, it doesn't have any side effects. You may want to
> use map instead or use puts
>
> e.g.:
>
> hand.each { |c| puts c.show }
>
> or hand.map { |c| c.show }

Ah! These work. Thank You!

I do recall from pickax that #each returns the array. It must be, then,
with

>hand.each { |c| c.show }

what I am seeing how irb displays an array.

IRB uses method #inspect of any object for display.

Does this mean that the
string returned by #show is produced, but nothing is telling it to
display so it sort of ... gets assigned to nothing, and dosn't display
in irb?

It doesn't even get assigned. The return value of #show is simply ignored.

But, then, why doesn't the block with the puts call first display the
strings followed by the display of the array returned by #each?

That we can only tell if you show us the code you used. Normally it's
exactly like you describe:

irb(main):004:0> %w{aa bb cc}.each {|c| puts c}
aa
bb
cc
=> ["aa", "bb", "cc"]

Follwing is the code defining the class (the rest I am just testing in
irb) for hal fulton, who asked for it. This is my first every ruby
program so it may be ugly, and could probably be improved upon. Been
programming in procedural languages since fortran 77, so this OO stuff
is a bit mind bending. But ... I like it!

Yeah, it took me some while to grasp it when I learned OO (Turbo
Pascal at that time). But the OO paradigm is much stronger than plain
procedural code IMHO.

You could for example create individual classes for suit, face and
maybe also for value implementing the enum pattern, so you end up
having just a single instance for hearts, clubs, face_up, face_down
etc.

Kind regards

robert

···

2006/7/8, william robb <otherwill@yahoo.com>:

--
Have a look: http://www.flickr.com/photos/fussel-foto/

Robert Klemme wrote:

You could for example create individual classes for suit, face and
maybe also for value implementing the enum pattern, so you end up
having just a single instance for hearts, clubs, face_up, face_down
etc.

I'd much rather stick with a single class, and use some of Ruby's goodness to get the magic:

   class Card
     SUITS = [:hearts, :clubs, :diamonds, :spades]
     RANKS = (1..13).to_a

     attr_reader :suit, :rank

     def initialize(suit, rank)
       @suit, @rank = suit.to_sym, rank.to_int

       raise unless SUITS.include? @suit
       raise unless RANKS.include? @rank
     end

     # creates the methods #hearts?, #clubs?, #diamonds?, and #spades?
     SUITS.each{|suit| define_method("#{suit}?"){ suit == @suit }}

     # etc. etc.
   end

But that's a matter of opinion, of course.

Cheers,
Daniel

Robert Klemme wrote:
[ .. snip ..]

Thanks for the explanation. I am a bit hazy on what is getting returned
and displayed in irb, but the structure of oo is comming clearer. I was
simply returning a string from the #show method, and letting irb do the
actual 'display', which explaned what was happening.

Been
programming in procedural languages since fortran 77, so this OO stuff
is a bit mind bending. But ... I like it!

Yeah, it took me some while to grasp it when I learned OO (Turbo
Pascal at that time). But the OO paradigm is much stronger than plain
procedural code IMHO.

The origional Turbo Pascal? That came on one 5 1/4 inch diskette, the
first IDE I'd ever seen? That wasen't OO, that was stright-up pascal,
no?

I guess you could call VBA/Excel OO, I've messed around with that, but
don't like it all that much. OK to scrap out stuff, automate a chart
for a client or something ... but I can't stand all the
'clickey-clickey' windows interface you have to plow through just to put
in a bit of code.

But, enough chat. I am really interested in what you are saying below.
I had a vauge notion to do this, but couldn't develop the syntax to
express what I wanted. If you wouldn't mind, I would appreciate an
example or two.

···

You could for example create individual classes for suit, face and
maybe also for value implementing the enum pattern, so you end up
having just a single instance for hearts, clubs, face_up, face_down
etc.

Kind regards

robert

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

william robb wrote:

Robert Klemme wrote:
[ .. snip ..]

Thanks for the explanation. I am a bit hazy on what is getting returned and displayed in irb, but the structure of oo is comming clearer. I was simply returning a string from the #show method, and letting irb do the actual 'display', which explaned what was happening.

Right.

Been
programming in procedural languages since fortran 77, so this OO stuff
is a bit mind bending. But ... I like it!

Yeah, it took me some while to grasp it when I learned OO (Turbo
Pascal at that time). But the OO paradigm is much stronger than plain
procedural code IMHO.

The origional Turbo Pascal? That came on one 5 1/4 inch diskette, the first IDE I'd ever seen? That wasen't OO, that was stright-up pascal, no?

V 5.5 was OO - I'm not sure whether that was the first OO version.

I guess you could call VBA/Excel OO, I've messed around with that, but don't like it all that much. OK to scrap out stuff, automate a chart for a client or something ... but I can't stand all the 'clickey-clickey' windows interface you have to plow through just to put in a bit of code.

:-))

But, enough chat. I am really interested in what you are saying below. I had a vauge notion to do this, but couldn't develop the syntax to express what I wanted. If you wouldn't mind, I would appreciate an example or two.

You could for example create individual classes for suit, face and
maybe also for value implementing the enum pattern, so you end up
having just a single instance for hearts, clubs, face_up, face_down
etc.

# poor mans enum pattern,
# for others see the RAA

Suit = Struct.new :name

class Suit
   VALUES = [
     HEARTS = new("Heart").freeze,
     CLUBS = new("Clubs").freeze,
     DIAMONDS = new("Diamonds").freeze,
     SPADES = new("Spades").freeze,
   ].freeze

   def to_s() name end

   def self.from_string(s)
     VALUES.detect {|su| s == su.name}
   end

   # restrict to the 4 instances created above
   def self.new(*a,&b) raise "Not allowed" end
end

Now you can do
Suit::HEARTS
Suit::VALUES.each {|s| puts s}
Suit.from_string "Hearts"
etc.

And also

case x.suit
   when Suit::HEARTS
     then puts "doing something with hearts..."
   when Suit::CLUBS
....
end

Kind regards

  robert

Thanks for the code. I will have to digest the syntax a bit to see
exactly
what you are doing here ... I had wondered what .freeze was good for.

On that other topic, I think it was around V5 that turbo pascal became
OO.
The first version was what made Borland a success, as it was a dirt
simple
implementation of a real programming language, with one of the first
IDEs. I still have the manual, complete, about the size of a paperback.

I do remember thinking, when I encountered Pascal's Record data type; "I
wish I could store a procedure in one of these fields ..." People at
Borland must have
thought that too, eh?

Then came C, and Pascal kinda withered away ... Wasen't 'cool', but was
a good workhorse.

Thanks again,

Will

You could for example create individual classes for suit, face and
maybe also for value implementing the enum pattern, so you end up
having just a single instance for hearts, clubs, face_up, face_down
etc.

# poor mans enum pattern,
# for others see the RAA

Suit = Struct.new :name

class Suit
   VALUES = [
     HEARTS = new("Heart").freeze,
     CLUBS = new("Clubs").freeze,
     DIAMONDS = new("Diamonds").freeze,
     SPADES = new("Spades").freeze,
   ].freeze

[..etc...]

···

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

(late reply due to holidays)

william robb wrote:

Thanks for the code. I will have to digest the syntax a bit to see exactly
what you are doing here ... I had wondered what .freeze was good for.

It prevents changing of an object. You probably found out by now...

irb(main):001:0> s="foo"
=> "foo"
irb(main):002:0> s.gsub! /./, 'x'
=> "xxx"
irb(main):003:0> s.freeze
=> "xxx"
irb(main):004:0> s.gsub! /./, 'y'
TypeError: can't modify frozen string
         from (irb):4:in `gsub!'
         from (irb):4

On that other topic, I think it was around V5 that turbo pascal became OO.

Or even 5.5 - I'm not 100% sure.

The first version was what made Borland a success, as it was a dirt simple
implementation of a real programming language, with one of the first IDEs. I still have the manual, complete, about the size of a paperback.

And the compiler was very fast because it was a one pass compiler (like all PASCAL compilers, it's made possible by the language's design).

I do remember thinking, when I encountered Pascal's Record data type; "I wish I could store a procedure in one of these fields ..." People at Borland must have
thought that too, eh?

Maybe they even read your mind - or NSA trapped your phone. :slight_smile:

Then came C, and Pascal kinda withered away ... Wasen't 'cool', but was a good workhorse.

Personally I still find PASCAL a pretty good language for learning to program since it makes many things rather explicit. IO of standard PASCAL is bad though. MODULA was a complete disaster IMHO - good ideas but implemented awfully. IIRC you needed to call a different IO function for every different basic data type - no polymorphism.

Kind regards

  robert

···

from :0