On 7/4/07, Mathew Snyder <[EMAIL PROTECTED]> wrote:

>> foreach my $user (keys %tickets) {
>>         foreach my $env (keys %{ $tickets{$user} }) {
>>                 foreach my $tikID (keys %{ $tickets{$user}{$env} }) {
>>                         foreach my $subject (keys %{
>> $tickets{$user}{$env}{$tikID} }) {
>
> You're doing the same dereferencing, just getting deeper each time.
> You'll save some time if you make some of those into temporary
> variables. That fourth nested loop could look more like this, but
> possibly with better variable names:
>
>        my $subjects_hash = $envs_hash->{$env};
>        foreach my $subject (keys %$subjects_hash) {
>

Can you explain the reason for skipping the {$id} portion and assigning the
{$env} portion to %subjects_hash?  The logic eludes me.

Maybe I've put the parts together wrong, or named them poorly. But the
general idea is that most references are copied to scalars, so that
you don't have to dereference $tickets{$user} as part of every
variable you access within four nested loops. That's probably going to
give you clearer code, but it will also be faster to execute.

The outer loop looks like this:

 foreach my $user (keys %tickets) {

Since there's just one value for $user each time through the loop,
$tickets{$user} will have just one value each time through the loop.
So instead of doing that hash lookup again and again, we'll keep the
result in a scalar.

   my $users_tix = $tickets{$user};

Since the scalar is declared just inside the loop, its scope ends at
the same place that $user's scope ends. So any line of code that used
to use $tickets{$user} can now use $users_tix just as well. (If their
scopes ended in different places, those two expressions wouldn't
always be interchangeable.)

Of course, the scalar could have been named $tickets_for_user or
$current_users_tickets, or something that does a better job of
matching what it's really about. I'm not clear on the nature of the
overall task or I'd have more confidence in my choice of name. I hope
that the technique is clear enough.

So, from now on, whenever we need $tickets{$user}, we can use
$users_tix. And we need it in the next nested loop, which used to look
like this:

   foreach my $env (keys %{ $tickets{$user} }) {

But now it looks like this:

   foreach my $env (keys %{ $users_tix }) {

Or, because the curly braces are optional around a just-plain-scalar,
many people prefer this:

   foreach my $env (keys %$users_tix) {

Using the same trick another level down, we get the easy way to write
$tickets{$user}{$env} , which could also be written
$tickets{$user}->{$env} :

     my $users_env = $users_tix->{$env};

The small arrow is optional in $tickets{$user}->{$env} because the
other punctuation is sufficient. If there are curly braces or square
brackets on both sides of the arrow, or one of each, the small arrow
may be omitted. But it reappears in the line of code above; it's
mandatory here because there's no longer a "closing" piece of
punctuation to its left.

And so on. By the time you get to the body of the fourth nested loop,
each variable access has become significantly shorter, so each line of
code is that much more readable and speedy to execute.

Good luck with it!

--Tom Phoenix
Stonehenge Perl Training

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to