in reply to Re: Re: Understanding why strict prevents a use of local
in thread Understanding why strict prevents a use of local

Why not try something like:
sub execute { my %argsHash = ( Source => $source, Dest => $destination, Host => $host, Error => $error, ); &ccCopy(\%argsHash); } sub ccCopy { my $args = shift; print "Copy: $args->{Source} to $args->{Dest}\n"; }
That will do two things:
  1. Clean up your messy-looking code
  2. Make it so you stay out of procedural messes by fooling with global variables. (They're sorta like matches, but for big kids. You still don't want to play with them.)

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Replies are listed 'Best First'.
Re: Re: Re: Re: Understanding why strict prevents a use of local
by c (Hermit) on Oct 20, 2001 at 01:55 UTC
    i like this solution, however can i add to the hash reference being passed to each subroutine? i ask because my subroutines add to the information being handed down with each nesting:

    #!/usr/bin/perl -w use strict; my $source = "tftp"; my $destination = "run"; &first; sub first { my %argsHash = ( Source => $source, Destination => $destination, ); &second(\%argsHash); } sub second { my $args = shift; my $error = "problems!"; print "This works, but i need to pass the error value to the third subroutine, in addition to $args->{Source} and $args->{Destination}\n"; &third(); }

    its here that i get confused. not only do i need to pass the existing value of $args to the third subroutine, but i also need to pass the value of $error as well. i've tried a little experimenting with &third(\$args); and although its passed, its passed as a scalar rather than a hash it seems. i see that i can add the value of $error within the second subroutine, such as:

    $args->{Error} = $error;

    but i'm stuck on how to pass this new hash to the next subroutine.

    humbly -c

      Ahh, I see why you're confused. It's context again.

      Arguments passed to a subroutine are passed as a list. If you put in a hash, it'll be flattened into a list:

      my %hash = ( one => 1, two => 2, ); foo(%hash); sub foo { print join(' | ', @_), "\n"; }
      You can coerce these arguments into a hash inside your subroutine. It's not often done, though, because it's inefficient and prone to weird warnings if you don't have an even-sized list. Worse yet, if you want to pass a list and a hash, or a scalar and a hash, or anything else, you can't disambiguate between them:
      sub foo { my %hash = @_; } # works fine foo(%hash); # uh oh foo('nameofhash', %hash); # not good at all foo(@names, %hash);
      If you can coerce all of your arguments into scalars, it's a lot easier to deal with them. (It's also more efficient, if you have a large list.) That's one reason people pass things by reference:
      # pass a reference to %hash, which is a scalar foo(\%hash); sub foo { my $hashref = shift; }
      You'll have to dereference it if you want to treat it like a hash, but that's usually a small price to pay. Since the hash reference is already a scalar, you can pass it to other subs as is:
      sub foo { my $hashref = shift; # add data bar($hashref); } sub bar { my $hashref = shift; # manipulate data as above }
      A reference to a hash is already a scalar (that's the point), so it's not necessary to take another reference to it. You'll just end up balding, with lots of curly braces. :)
      my %argHash = ( abcd => 'efgh', ijkl => 'mnop', ); &first(\%argHash); sub first { my $args = shift; print "$_ => $args->{$_}\n" foreach sort keys %$args; &second({%$args, qrst => 'uvwx'}); } sub second { my $args = shift; print "$_ => $args->{$_}\n" foreach sort keys %$args; }
      Or, if you don't want to use hashrefs, you can do
      my %argHash = ( abcd => 'efgh', ijkl => 'mnop', ); &first(\%argHash); sub first { my %args = @_; print "$_ => $args->{$_}\n" foreach sort keys %args; &second(%$args, qrst => 'uvwx'); } sub second { my %args = @_; print "$_ => $args{$_}\n" foreach sort keys %args; }
      Note how the two use different braces at different times. Either is just fine. The second is prone to more errors in coercing the array @_ into the hash %args, but, so long as you know exactly what's going into that hash, you should be fine. Try them out and see which you prefer.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.