dimmesdale has asked for the wisdom of the Perl Monks concerning the following question:

The full code of the bits I'm posting will be on my scratch pad (for those daring enough).

A brief synopsis:

I have three modules: right now I'm trying to get one of them to work with the other two. I've got a Pile type; a Card type; and a Solitaire type. Solitaire is working with Card and Pile. A pile is a collection of cards. I working with a sub to delete a card from a pile, and am running into some problems. Here's the sub:

sub remove_card { # usage: $caller->remove_card() # removes top card of pile, returning its value my $self = shift; if($self->num() > 1) { # I've worked with many alterations of this, and this # seems (I repeat *seems*) to be what I want $self->cards( $self->cards()->[1..$self->num()-1] ); } else { $self->cards([]) } }

The cards() method, which has undergone some tweaking as a result of my debugging attempts, looks like this:

sub cards { # usage: $caller->cards([$cards]) # $cards is an anonymous array of Card types # return: cards in pile my $self = shift; if (@_) { $self->{cards} = shift; $self->num(int @{$self->{cards}}); # From data dumping, it seems that I need this line for(@{$self->cards()}) { $_->where($self) } } return $self->{cards}; }

I think the problem lies with the splice in the remove procedure. I'm getting an error 'Argument "" isn't numeric...' for $self->num() statements (in the if and the splice in the remove procedure)

Also, 'Not an ARRAY reference' for $self->num(int @{$self->{cards}}); in cards() method.

In remove_card(), here's a data dump -----------------------------------------------

$self->cards() returns $VAR1 = [ bless( { 'state' => 'down', 'where' => bless( { 'next' => 0, 'num' => 56, 'max' => 52, 'cards' => $VAR1 }, 'Pile' ), 'value' => 1, 'suit' => 'h' }, 'Card' ), ... bless( { 'state' => 'down', 'where' => $VAR1->[0]{'where'}, 'value' => 'k', 'suit' => 'd' }, 'Card' ) ]; @{$self->cards()}->[1..$self->num()-1] returns $VAR1 = bless( { 'state' => 'down', 'where' => bless( { 'next' => 0, 'num' => 56, 'max' => 52, 'cards' => [ $VAR1, bless( { 'state' => +'down', 'where' => +$VAR1->{'where'}, 'value' => +8, 'suit' => ' +c' }, 'Card' ), ... bless( { 'state' => +'down', 'where' => +$VAR1->{'where'}, 'value' => +'k', 'suit' => ' +d' }, 'Card' ) ] }, 'Pile' ), 'value' => 1, 'suit' => 'h' }, 'Card' );

It looks like the key 'where' is getting the correct pile, but the actual pile is NOT getting changed as needed.

Replies are listed 'Best First'.
Re: Perl OO and dereferincing help
by tadman (Prior) on Jul 12, 2002 at 02:22 UTC
    You should probably be accessing the data directly, and using something like pop or unshift instead of this naive reimplementation. I don't mean to sound harsh, but these are basic list operations, one of the things the Llama Book covers pretty much first thing. Learn them and use them. They are surprisingly efficient.

    The idea would be something like this:
    sub remove_card { my ($self) = @_; return pop(@{$self->{cards}}); # Returns nth element }
    So it would seem you're making a haystack out of a needle, to use a mangled metaphor.

    Your problem was that you were sending a list to your cards function, which you then use as an array reference. If you'd put square brackets around what you were passing it, it would've worked, but then, this is probably for the best because it would be really clunky.
    $self->cards([$self->cards()->[1..$self->num()-1]]);
    You'll note that you're calling the function twice, creating an anonymous array, and you still haven't even returned the correct value.
Re: Perl OO and dereferincing help
by djantzen (Priest) on Jul 12, 2002 at 02:36 UTC

    The first thing to note is that you could make your life much easier by utilizing shift() or pop() in your remove_card() method, which basically just reimplements that behavior.

    Secondly, it looks like somewhere num() is getting called with a string as a param. Try adding a print statement inside the method, or better, a check like $_[1] =~ /\d+/.

    Finally, it looks like remove_cards() calls cards() and supplies an array, not a reference to an array as cards() seems to expect. Update: Tadman rightly calls the former a list, not an array.

    Hope that's helpful.

Re: Perl OO and dereferincing help
by bronto (Priest) on Jul 12, 2002 at 13:00 UTC

    I would like to add to the useful suggestions by tadman and fever; I'd suggest to use a debugger with your test program to try to catch the point where the crap comes out.

    I am too lazy to learn the "plain" perl debugger (but laziness is a virtue for a Perl Programmer, as Saint LW says :-), so I use ptkdb, a visual perl debugger. It's easy to use and well documented.

    Of course, you will need tk.

    Ciao!
    --bronto

    # Another Perl edition of a song:
    # The End, by The Beatles
    END {
      $you->take($love) eq $you->made($love) ;
    }