The Perl You Need to Know, Part II: Working with Nested Subroutines Page 6

執筆者
Stas Bekman
Stas Bekman
Published: Jul 20, 2010
Updated: Nov 10, 2020
3 minute read
ServerWatch のコンテンツおよび製品のおすすめは、編集上の独立性を保っています。パートナーへのリンクをクリックすると、当社が報酬を得る場合があります。 詳細を見る



By the way, the warning we saw before has gone, and so has the problem,
since there is no my() (lexically defined) variable used in the nested subroutine.

Another approach is to use fully qualified variables. This is better, since
less memory will be used, but it adds a typing overhead:

  multirun2.pl
  -----------
  #!/usr/bin/perl -w
  
  use strict;
  
  for (1..3){
    print "run: [time sh]n";
    run();
  }
  
  sub run {
  
    ::counter = 0;
  
    increment_counter();
    increment_counter();
  
    sub increment_counter{
      ::counter++;
      print "Counter is equal to ::counter !n";
    }
  
  } # end of sub run

You can also pass the variable to the subroutine by value and make the
subroutine return it after it was updated. This adds time and memory
overheads, so it may not be good idea if the variable can be very large, or
if speed of execution is an issue.

Don’t rely on the fact that the variable is small during the development of
the application, it can grow quite big in situations you don’t expect. For
example, a very simple HTML form text entry field can return a few
megabytes of data if one of your users is bored and wants to test how good
your code is. It’s not uncommon to see users copy-and-paste 10Mb core dump
files into a form’s text fields and then submit it for your script to
process.

  multirun3.pl
  -----------
  #!/usr/bin/perl -w
  
  use strict;
  
  for (1..3){
    print "run: [time sh]n";
    run();
  }
  
  sub run {
  
    my  = 0;
  
     = increment_counter();
     = increment_counter();
  
    sub increment_counter{
      my  = shift;
  
      ++;
      print "Counter is equal to  !n";
  
      return ;
    }
  
  } # end of sub run

Finally, you can use references to do the job. The version of
increment_counter() below accepts a reference to the
variable and increments its value after first dereferencing it. When you
use a reference, the variable you use inside the function is physically the
same bit of memory as the one outside the function. This technique is often
used to enable a called function to modify variables in a calling function.

  multirun4.pl
  -----------
  #!/usr/bin/perl -w
  
  use strict;
  
  for (1..3){
    print "run: [time sh]n";
    run();
  }
  
  sub run {
  
    my  = 0;
  
    increment_counter($counter);
    increment_counter($counter);
  
    sub increment_counter{
      my  = shift;
  
      15080r_counter++;
      print "Counter is equal to 15080r_counter !n";
    }
  
  } # end of sub run

Here is yet another and more obscure reference usage. We modify the value
of inside the subroutine by using the fact that variables in @_ are aliases for the actual scalar parameters. Thus if you called a function
with two arguments, those would be stored in
sh[0] and sh[1]. In particular, if an element sh[0] is updated, the corresponding argument is updated (or an error occurs if it
is not updatable as would be the case of calling the function with a
literal, e.g. increment_counter(5)).

  multirun5.pl
  -----------
  #!/usr/bin/perl -w
  
  use strict;
  
  for (1..3){
    print "run: [time sh]n";
    run();
  }
  
  sub run {
  
    my  = 0;
  
    increment_counter();
    increment_counter();
  
    sub increment_counter{
      sh[0]++;
      print "Counter is equal to sh[0] !n";
    }
  
  } # end of sub run
Stas Bekman

Stas Bekman is a ServerWatch contributor.

ServerWatch Logo

ServerWatch is a top resource on servers. Explore the latest news, reviews and guides for server administrators now.

TechnologyAdvice が所有・運営しています。 © 2026 TechnologyAdvice. 無断転載を禁じます

広告主に関する開示:このサイトに掲載されている製品の一部は、TechnologyAdvice が報酬を受け取っている企業のものです。この報酬は、製品がこのサイトのどこにどのように表示されるか(表示される順序など)に影響する場合があります。TechnologyAdvice は、市場で入手可能なすべての企業やすべての種類の製品を掲載しているわけではありません。