The idea here is I want the initial hash to be run into the child function, have changes made, send the changes back to the parent. Then send the changed hash into the child for more changes to take place. I've been making a poker program to help me learn, and here are the functions in question:

It might not be the best way to make poker, but I did it like this in python and it worked.

#hand is fed 5 cards(an array) to be analyzed for what they're worth. The function #is all called with a number to indicate which player it is.
sub hand {
    my($cards) = shift;
    my %ply1score = (2 => "0", 3 => "0", 4 => "0", 5 => "0", 6 => "0", 7 => "0",
                     8 => "0", 9 => "0", 10 => "0", 11 => "0", 12 => "0", 13 => "0",
                     14 => "0", s => "0", c => "0", d => "0", h => "0");

    my %ply2score = (2 => "0", 3 => "0", 4 => "0", 5 => "0", 6 => "0", 7 => "0",
                     8 => "0", 9 => "0", 10 => "0", 11 => "0", 12 => "0", 13 => "0",
                     14 => "0", s => "0", c => "0", d => "0", h => "0");
    for (@$cards){
         print "card: $_\n";
         my @whatisit = split;
         if ($_[0] eq 1){ 
             calc($whatisit[0],$whatisit[2], %ply1score);
         }
         if ($_[0] eq 2){
             calc($whatisit[0],$whatisit[2], %ply2score);
         }
     }
}

sub calc {
    my $face = $_[0];
    my $suit = $_[1];
    my %score = @_;
    if ($face eq "Ace") {
        $score{14}++;
    }
    if ($face eq "Two") {
        $score{2}++;
    }
    if ($face eq "Three") {
        $score{3}++;
    }
    if ($face eq "Four") {
        $score{4}++;
    }
    if ($face eq "Five") {
        $score{5}++;
    }
    if ($face eq "Six") {
        $score{6}++;
    }
    if ($face eq "Seven") {
        $score{7}++;
    }
    if ($face eq "Eight") {
        $score{8}++;
    }
    if ($face eq "Nine") {
        $score{9}++;
    }
    if ($face eq "Ten") {
        $score{10}++;
    }
    if ($face eq "Jack") {
        $score{11}++;
    }
    if ($face eq "Queen") {
        $score{12}++;
    }
    if ($face eq "King") {
        $score{13}++;
    }
    if ($suit eq "Diamonds") {
        $score{d}++;
    }
    if ($suit eq "Clubs") {
        $score{c}++;
    }
    if ($suit eq "Hearts") {
        $score{h}++;
    }
    if ($suit eq "Spades") {
        $score{s}++;
    }
    return %score;
}

So after checking for the face and suit, there should be a change of values from 0 to 1. Which there is for %score. But once returned I would like ply1score to see that as well, but it stays at 0 throughout.

Dani AI

Generated

Short answer: the child is getting a copy of the flattened hash, not the original, so changes never affect the parent. There are two common, safe fixes: pass a reference and mutate that reference in place, or return the updated structure and reassign it in the caller. Neither requires globals.

Why your code behaves that way (clarification)

  • When you call a sub with a hash (or include a hash in the argument list) Perl "flattens" it into @_ and you rebuild a new hash inside the callee (so modifications are to the copy). That is the core reason the %ply1score values stay 0.
  • Also, the call to shift in your hand sub removes the first argument from @. Tests like `$[0] eq 1` inside the loop will then be wrong or empty — capture all parameters explicitly instead of relying on @_ after using shift.

Practical, actionable guidance

  • Keep your per-player score hashes in the caller. When calling the helper, pass a reference to the correct hash (or to a player-structure). Have the helper accept that scalar reference and update the hash by dereferencing. That avoids copying and is efficient.
  • Alternatively, have the helper return the updated hash (or a hashref) and assign it back in the parent — this is explicit but involves copying.
  • Prefer lexically scoped variables (my) and use strict; use warnings; so you catch signature/typo bugs early.

Testing and next steps

  • Print the caller's hash (or use Data::Dumper) immediately before and after the helper call to confirm whether you mutated in place or replaced it.
  • For a longer-term design, consider using structured hands (arrayrefs of card hashes) and either a player hash or an OO wrapper; ’s pointer to using objects/modules is a good refactor target. Avoid globals (as suggested) unless you need them for a truly global state.

Recommended Answers

All 7 Replies

This is never going to work:

my $face = $_[0];
my $suit = $_[1];
my %score = @_;

What I would do is pass the reference to %score like this:

my $score=calc($whatisit[0],$whatisit[2], \%ply2score);
print "score for hearts: $$score->{h}";
sub calc{
   my ($face,$suit,$score)=@_;
   #do something to calculate
   if ($suit eq "Hearts") {
        $$score{h}++;
   }
   return $score;
}

I think you ought to look into complex data structures. You can push a has within a hash or and array in a hash. You can pass the entire thing back and forth, either as references or actual structures.

I don't have time today to show you how, but look into data structures in perl.

This is never going to work:

my $face = $_[0];
my $suit = $_[1];
my %score = @_;

What I would do is pass the reference to %score like this:

my $score=calc($whatisit[0],$whatisit[2], \%ply2score);
print "score for hearts: $$score->{h}";
sub calc{
   my ($face,$suit,$score)=@_;
   #do something to calculate
   if ($suit eq "Hearts") {
        $$score{h}++;
   }
   return $score;
}

I think you ought to look into complex data structures. You can push a has within a hash or and array in a hash. You can pass the entire thing back and forth, either as references or actual structures.

I don't have time today to show you how, but look into data structures in perl.

MMk, ill take a look at this tomorrow as well as some data structures and take it from there. thanks

You may declare the %score as a global variable, then you able to access the variable across the program for the updated values

Try below codes in your declaration part.

### declare the global variable ...
our %score

Otherwise

## the declared variable considered as the global variable
use vars qw(%score $var1 $var2 @array1);

For More details:-
http://search.cpan.org/~jesse/perl-5.12.2/lib/vars.pm

The way to really do this right is to use something like:

http://search.cpan.org/~akarger/Games-Cards-1.45/lib/Games/Cards.pm

or

http://search.cpan.org/~pip/Games-Cards-Poker-1.2.565CHh5/Poker.pm

Those are modules that hold the cards/hands and shuffle and other such functions.

But if you want to dip your toe into data structures, you can try this:

use strict;
use warnings;

my %names=("1"=>"Ace","2"=>"Two","3"=>"Three","4"=>"Four","5"=>"Five","6"=>"Six","7"=>"Seven","8"=>"Eight","9"=>"Nine","10"=>"Ten","11"=>"Jack","12"=>"Queen","13"=>"King");
my @suits=qw(Spades Hearts Clubs Diamonds);

my @deck;
for (@suits){
	my $csuit=$_;
	for (keys %names){
		my %card = ("suit"=>"$csuit","value"=>"$_","name"=>"$names{$_} of $csuit");
		push @deck,\%card;
	}
}
for (@deck){
	print "$_->{name}\n";
}

Then, you can create a hand array and pass that back and forth. If you want you can create a player hash with the player number as the key and pointing to the hand array.

my %players=("1"=>\@hand1, "2"=>\@hand2);

or something like that.

Probably wouldnt hurt to do some toe dipping. Helps with the learning and such.

Dip away! If you want to jump in headfirst, use Moose - which is an object-oriented add-on for perl. That way you can crate the cards as objects with functions/methods. So, you can ask a card what it's value/score is. However, if you don't want to jump in that deep yet, I'd suggest using the references and data structures like above.

Remember that perl allows you to get a pointer (reference) to anything via a scalar.

my @array=qw (one two);
my $scalar=\@array;
print "$$scalar[0]\n";
my %hash=("key",$scalar);
print "${$hash{key}}[1]\n";
my @array1;
push @array1,\%hash;
print "$array1[0]->{key}[0]\n";

The last line is an array that contains a reference to a hash that in turn contains a reference to another array keyed by the word "key". You can go on and on and on.

As for your card game, think about what types each element should be. Cards should probably be hashes. Decks and Hands should be arrays. Players should be hashes that hold arrays (hands) and their names, scores, etc stored as hash values.


It's a lot like C without the memory management problems.

Dip away! If you want to jump in headfirst, use Moose - which is an object-oriented add-on for perl. That way you can crate the cards as objects with functions/methods. So, you can ask a card what it's value/score is. However, if you don't want to jump in that deep yet, I'd suggest using the references and data structures like above.

Remember that perl allows you to get a pointer (reference) to anything via a scalar.

my @array=qw (one two);
my $scalar=\@array;
print "$$scalar[0]\n";
my %hash=("key",$scalar);
print "${$hash{key}}[1]\n";
my @array1;
push @array1,\%hash;
print "$array1[0]->{key}[0]\n";

The last line is an array that contains a reference to a hash that in turn contains a reference to another array keyed by the word "key". You can go on and on and on.

As for your card game, think about what types each element should be. Cards should probably be hashes. Decks and Hands should be arrays. Players should be hashes that hold arrays (hands) and their names, scores, etc stored as hash values.


It's a lot like C without the memory management problems.

Haha dont say that. I tried learning C and its such a harsh language. I've never been into code when i was younger and slowly gotten into scripting languages.

Anyway, my overall plan with this learning exercise was to build it sequentially, and then refactor it to use classes and such. Ill see if i can grasp these data structures first.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.