Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > newbie Q - calling a method for an object in an .each block?

Reply
Thread Tools

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

 
 
william robb
Guest
Posts: n/a
 
      07-08-2006
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/.

 
Reply With Quote
 
 
 
 
Hal Fulton
Guest
Posts: n/a
 
      07-08-2006
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

 
Reply With Quote
 
 
 
 
Logan Capaldo
Guest
Posts: n/a
 
      07-08-2006

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/.
>


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 }


 
Reply With Quote
 
william robb
Guest
Posts: n/a
 
      07-08-2006
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/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      07-08-2006
2006/7/8, william robb <(E-Mail Removed)>:
> 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

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

 
Reply With Quote
 
Daniel Schierbeck
Guest
Posts: n/a
 
      07-08-2006
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

 
Reply With Quote
 
william robb
Guest
Posts: n/a
 
      07-09-2006
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/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      07-09-2006
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


 
Reply With Quote
 
william robb
Guest
Posts: n/a
 
      07-11-2006
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/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      07-30-2006

(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
from :0

> 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.

> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dumb question: in documentation, why Object#method, and not Object.method ? Elf M. Sternberg Ruby 15 07-29-2009 01:20 AM
problem calling method from parent of an object if object relayson template arguments of current template class? =?UTF-8?B?UmFmYcWCIE1haiBSYWYyNTY=?= C++ 2 03-02-2006 05:45 AM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Calling a method of the calling object ... why-em-jay Perl Misc 3 09-15-2005 07:53 PM
Problems with JNI: calling a Java method from native method. Jabel D. Morales - VMan of Mana Java 1 08-01-2003 12:18 PM



Advertisments