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

Dear Monks, I need to keep track of all objects created so eventually each object with pick a random object (other then its self) and act upon it. Why is this not working and what is a better way to implement this procedure? Thanks Monks!
#!/usr/bin/perl use strict; use warnings; use User; my $test = User->new(name => "user1", team=> "teamalpha"); my $test2 = User->new(name => "user2", team=> "teambeta"); $test->test(); $test2->test(); package User; use strict; use warnings; my $references; sub new { my ($class, %arg) = @_; my $objref = { _name => $arg{name} || "unknow +n" _team => $arg{team} || "unknow +n" }; bless $objref, $class; $references->{$objref} = "value"; return $objref; } sub test { my $self = shift @_; foreach my $object (keys %$ds) { if($self->{_team} ne $object->{_team}) { #find opposing team #do something to $object } } }

Replies are listed 'Best First'.
Re: Perl OO - Class Data
by Tanktalus (Canon) on Jun 26, 2006 at 16:11 UTC

    In general, you can't use objects as keys to a hash.

    Given your current usage pattern, I would suggest reversing everything and, instead of $references->{$objref} = "value", try:

    $references->{$objref->{_team}}{$objref->{_name}} = $objref;
    That's assuming that no two objects can have the same name. If that's not the case, perhaps you really want arrays:
    push @{$references->{$objref->{_team}}}, $objref;
    Both examples here split everything up by team so that you can just skip over an entire hash or array rather than skipping over individual team members.

    (This is in addition to japhy's advice to use the same variable name to refer to the same object ;-})

      In general, you can't use objects as keys to a hash.

      Just to expand on that a little...

      If you attempt to use an object as a hash key, Perl will convert the reference to a text string and use that as the actual hash key. While this is quite handy for generating unique IDs, it also means that the keys of the hash are no longer usable as objects. (This applies to all references, actually, not just objects.)

      So using keys %ds to retrieve your User objects can't work. However, if you construct %ds with $ds{$objref} = $objref (the posted code doesn't put any data into %ds, so I don't know whether that's how you're doing it or not), then you should be able to retrieve all your objects using values %ds in your foreach.

      But it also looks like your test sub, in addition to only looking for Users on the opposing team, is also going against every one of them rather than a random one. If you want randomness, then you'll probably want to do something like

      my @objlist = values %ds; my $randobj = $objlist[rand @objlist];
        That cleared up a lot of confusion for me. Thanks!!!
Re: Perl OO - Class Data
by Moron (Curate) on Jun 26, 2006 at 16:52 UTC
    FWIW, what I do in these situations is create a separate grouping class whose job is to contain references to all the objects in the individuals (here User) class. e.g.:
    use User; package Community; sub new { my $self = shift; $self = {}; my @tmp = (); $self -> { USERS } = \@tmp; return bless $self; } sub adduser { # add a User object to this container object my $self = shift; my $aref = $self -> { USER }; push @$aref, shift(); } sub retch { # destructive random fetch of User # from this container object my $self = shift; my $aref = $self -> { USER }; return splice( @$aref, rand() * $#$aref ); } 1;

    -M

    Free your mind

Re: Perl OO - Class Data
by japhy (Canon) on Jun 26, 2006 at 15:50 UTC
    Perhaps if you used %$references instead of %$ds in your test() method, it would work. And do you want to work on a different object or an object on a different team? Right now, your code looks for an object on a different team.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Perl OO - Class Data
by NetWallah (Canon) on Jun 26, 2006 at 16:03 UTC
    Update2 Ignore this first suggestion(See ikegami's comment below)
    Shouldnt that be
    our $references;
    instead of "my $references;" ?

    Update1:
    How about:

    my @references; # -- inside new() push @references, $objref; # #.. inside sub test() .. # foreach my $object(@references){ ....}

    Update 3:
    Since I fuffled previous responses, I spent some time getting this thing working (and also understanding how perl OO works). The working code below may help the OP. The idea for the "Team" package is based on Moron's(++) post, below.

         "For every complex problem, there is a simple answer ... and it is wrong." --H.L. Mencken

      What's wrong with my $references;? Using my prevents other modules from mucking with $references.

Re: Perl OO - Class Data
by eric256 (Parson) on Jun 26, 2006 at 19:50 UTC

    If you are going to build test code like that, it would be nice if you at least ran it. That code has a couple of obvious errors that would have been caught simply by running it. Instead you popped it up here for us to debug for you. I think that is taking the lazyness virtue a bit to far. In the future please *run* your sample code before posting it. Yes I know its a pasting error, or a typo or whatever.


    ___________
    Eric Hodges