in reply to Not quite an OO tutorial

Thank you for taking the time to type this all out for everyone and me. Have a cookie! Now, I have some questions, though they aren't about OO specifically.

  1. How would you control explosive growth with this? I could sneeze and come up with a new list of items that I would like to randomize. Do I just keep adding new things to the top under RandThing and maybe keeping a list in a comment? The current set up looks a bit bulky for all of the randomizing I would be doing with this. Below are two lists I came up with while sitting here, and I may actually use them some day.
    package RandWritingImplement; use parent -norequire, 'RandThing'; sub new { my ($class) = @_; my @values = qw(pencil pen marker crayon chalk); return $class->SUPER::new (@values); } package RandWritingSurface; use parent -norequire, 'RandThing'; sub new { my ($class) = @_; my @values = qw(paper parchment slate hide stone); return $class->SUPER::new (@values); }
  2. How would RandThing be modified to accept not only arrays but also hashes? There are times where the list comes from a single hash key, the list could be the hash keys, or all of the arrays in the hash jumbled into one large list. Below is a subroutine I wrote which does it all for me, except that it doesn't take direct input.
    sub _random { my ($list,$key) = @_; my @random_array; if (ref($list) eq "HASH") { if ($list->{$key}) { @random_array = @{$list->{$key}}; } elsif ($key eq 'keys') { @random_array = (keys %{$list}); } elsif ($key eq 'all') { @random_array = map(@{$list->{$_}},keys %{$list}); } else { die q(You need to select a key from the hash, "all" keys, or jus +t "keys".); } } elsif (ref($list) eq "ARRAY") { @random_array = @{$list}; } else { die q(What are you doing? You didn't enter a hash or an array.); } return $random_array[rand @random_array]; }

These are two issues that I don't see an answer for in the current set up. OO does sound appealing, however, it appears to be very bulky for even something as simple as randomizing a lot of lists.

Have a cookie and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re^2: Not quite an OO tutorial
by GrandFather (Saint) on Feb 27, 2011 at 09:32 UTC

    First off remember that the sample code in the OP was intended as demo code that touches a little on a real problem, but isn't intended as a serious solution to the original problem. In particular it doesn't scale well - that is, it really is a bad solution if you want to add many, many different groups of random things.

    A better solution if you want to add many different types of random things is to write a class that addresses that issue. There are many ways you could do that. Given that the list is likely to grow over time and that groups of things may be added at run time having a few different ways of adding groups is probably needed. I'd start with something like this:

    use strict; use warnings; package RandThing; use overload '""' => 'getValue'; my %_groups; # Load default groups while (<DATA>) { chomp; next if ! length; my ($type, @values) = split /,/; $_groups{$type} = \@values; } return 1; sub new { my ($class, $type, @values) = @_; die "RandThing::new must be called using RandThing->new ('type') s +yntax!\n" if ! defined $class || ref $class; die "$class->new requires a group type parameter\n" if ! defined $type; die "Group type $type is unknown and no values given to define a n +ew type\n" if ! exists $_groups{$type} && ! @values; if (! @values) { # Use an existing group @values = @{$_groups{$type}}; } elsif (ref $values[0]) { $_groups{$type} = \(@values = doLAMagic (@values)); } else { # Add a new group or update an old one $_groups{$type} = \@values; } my $self = bless {values => \@values}, $class; $self->genValue (); return $self; } sub doLAMagic { my ($list, $key) = @_; my @values; return @$list if 'ARRAY' eq ref $list; return @{$list->{$key}} if exists $list->{$key}; return keys %{$list} if $key eq 'keys'; return map (@{$list->{$_}}, keys %{$list}) if $key eq 'all'; $key = 'undef value' if ! defined $key; die "Can't do LA magic on a hash using $key. 'keys' or 'all' requi +red"; } sub getValue { my ($self) = @_; return $self->{value}; } sub genValue { my ($self) = @_; $self->{value} = $self->{values}[rand @{$self->{values}}]; return $self->{value}; } __DATA__ Weather,stormy,windy,rainy,calm Light,bright,dark,gloomy,dazzling DayPart,morning,evening,afternoon,night

    which can be used in similar fashion to the previous sample:

    use strict; use warnings; use RandThing; my $dp = RandThing->new ('DayPart'); my $lt = RandThing->new ('Light'); my $wt = RandThing->new ('Weather'); my $tense = RandThing->new ('Tense', 'was', 'is', 'will be'); my $la = RandThing->new ('LA', [qw(Lady Aleena magic)]); print "It $tense a $lt and $wt $dp ($la).\n";

    Now you still have the overload magic, a bunch of default group types, the ability to add new group types and a simple way of extending the list of default group types. Oh, and for good measure I tossed in some Lady Aleena magic ;).

    True laziness is hard work