Using 'my' within nested loops

Ask a Question related to PERL Miscellaneous, Design and Development.

  1. #1

    Default Using 'my' within nested loops

    I am curious about the amount of overhead created with the first example
    below as compared to the second example below:


    Example 1:
    my $this;
    my $that;
    foreach $this (@somearray) {
    foreach $that (@some_other_array) {
    ........
    }
    }


    Example 2:
    foreach my $this (@somearray) {
    foreach my $that (some_other_array) {
    .......
    }
    }


    It seems to me that while the second example does a better job of limiting
    the scope of variables just to the block in which they're applicable, the
    second example does cause the construction of a variable each time the outer
    foreach iterates.

    Is the overhead caused by constructing and deconstructing a variable over
    and over again as it comes into and falls out of scope a degree of extra
    overhead that could hamper execution speed on tight loops? Is this even an
    issue?

    I apologize for using "constructing" and "deconstructing"... just a loose
    use of those words.

    Dave






    --
    DJO


    David Oswald Guest

  2. Similar Questions and Discussions

    1. Nested loops?
      Hi, I've been adapting a script which parses HTML and creates an RSS feed (http://www.perl.com/lpt/a/2001/11/15/creatingrss.html). Now I want...
    2. HTML::Template arbitraryily nested recursive loops
      Can anyone suggest a way to display an arbitrarily deep nested loop structure using HTML::Template? Below is what I've tried. I have a data...
    3. Possible Bug w/ nested loops and queries
      May have found a possible bug... can someone please verify? In a database I have two tables, temp1 and temp2 These tables can contain anything,...
    4. [PHP] nested for loops
      your syntax is correct, just need to change for ($j=0: $j < 5; $j++) to for ($j=0; $j < 5; $j++) Anyone ever do a nested for loop? $i =0; $j...
    5. nested for loops
      Anyone ever do a nested for loop? $i =0; $j =0; for ($x=0; $x < 50; $x++){ echo ("1 to 50"); for ($j=0: $j < 5; $j++) { echo ("less than...
  3. #2

    Default Re: Using 'my' within nested loops

    David Oswald wrote:
    > I am curious about the amount of overhead created with the first example
    > below as compared to the second example below:
    >
    >
    > Example 1:
    > my $this;
    > my $that;
    > foreach $this (@somearray) {
    > foreach $that (@some_other_array) {
    > ........
    > }
    > }
    >
    >
    > Example 2:
    > foreach my $this (@somearray) {
    > foreach my $that (some_other_array) {
    > .......
    > }
    > }
    >
    >
    > It seems to me that while the second example does a better job of limiting
    > the scope of variables just to the block in which they're applicable, the
    > second example does cause the construction of a variable each time the outer
    > foreach iterates.
    >
    > Is the overhead caused by constructing and deconstructing a variable over
    > and over again as it comes into and falls out of scope a degree of extra
    > overhead that could hamper execution speed on tight loops? Is this even an
    > issue?

    Why don't you:

    use Benchmark;

    and find out?


    ....
    > Dave
    ....

    > --
    > DJO
    ....


    --
    Bob Walton

    Bob Walton Guest

  4. #3

    Default Re: Using 'my' within nested loops

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    "David Oswald" <spamblock@junkmail.com> wrote in
    news:vhp11c9c2fgd7b@corp.supernews.com:
    > Is the overhead caused by constructing and deconstructing a variable
    > over and over again as it comes into and falls out of scope a degree
    > of extra overhead that could hamper execution speed on tight loops?
    > Is this even an issue?
    My off-the-cuff answer: Probably not. You might shave a millisecond or two
    off each loop iteration, but unless you're up against a wall, that probably
    won't make much difference. If it does, perhaps Perl is not the right
    language for your application.

    Disclaimer: I haven't done any timings; this is just a gut answer from
    experience.
    - --
    Eric
    $_ = reverse sort qw p ekca lre Js reh ts
    p, $/.r, map $_.$", qw e p h tona e; print

    -----BEGIN PGP SIGNATURE-----
    Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

    iQA/AwUBPxyNoWPeouIeTNHoEQLcMACg9XzrzRKzESATDIkxobfkcg ZjOSsAoPJG
    ezdXWoBHkusM1/npZQFSvhPR
    =AB2E
    -----END PGP SIGNATURE-----
    Eric J. Roode Guest

  5. #4

    Default Re: Using 'my' within nested loops


    "Bob Walton" <bwalton@rochester.rr.com> wrote in message
    news:3F1C88B9.5060706@rochester.rr.com...
    > David Oswald wrote:
    >
    > > I am curious about the amount of overhead created with the first example
    > > below as compared to the second example below:
    > >
    > > Example 1:
    > > my $this;
    > > my $that;
    > > foreach $this (@somearray) {
    > > foreach $that (@some_other_array) {
    > > ........
    > > }
    > > }
    > >
    > >
    > > Example 2:
    > > foreach my $this (@somearray) {
    > > foreach my $that (@some_other_array) {
    > > .......
    > > }
    > > }
    > >
    > Why don't you:
    >
    > use Benchmark;
    >
    > and find out?
    >
    Thanks for the suggestion. I just tried it (and should have thought of that
    myself).

    Here's the test code I used:

    #!/usr/bin/perl -w

    use strict;
    use warnings;
    use Benchmark;

    my ($count, $this, $that, $t0, $t1, $td, @array1, @array2);

    foreach (1..4000) {
    push @array1,$_;
    push @array2,$_;
    }
    $count = 0;
    print "Beginning test 1.\n";
    $t0 = new Benchmark;
    foreach $this (@array1) {
    foreach $that (@array2) {
    $count++;
    }
    }
    $t1 = new Benchmark;
    $td = timediff ($t1, $t0);
    print "Test 1 took: ", timestr ( $td ), "\n";
    $count = 0;
    print "Beginning test 2. \n";
    $t0 = new Benchmark;
    foreach my $those (@array1) {
    foreach my $these (@array2) {
    $count++;
    }
    }
    $t1 = new Benchmark;
    $td = timediff ($t1, $t0);
    print "Test 2 took: ", timestr ( $td ), "\n";


    The number of iterations was sufficient to tie up about 30 seconds per test
    block on my measly old Windows98 Pentium II/266 notebook (my Perl testbed).

    I ran it a couple times. The first time I ran it, the first testcase
    (without the "my"'s inside the loops) took 33 seconds and the second
    testcase (with the my's in the loop) took 32. The second time I ran it the
    results were reversed, 32 and 33. So I guess the answer is that putting my
    inside a tight loop doesn't increase overhead and runtime. Of course I
    don't know if that's always the case. It could be that my simplified test
    interprets and compiles differently than if the loops had more complexity
    inside. But that's probably a different discussion.

    Thanks all.

    Dave



    David Oswald Guest

  6. #5

    Default Re: Using 'my' within nested loops

    "David Oswald" <spamblock@junkmail.com> writes:
    > I am curious about the amount of overhead created with the first example
    > below as compared to the second example below:
    >
    >
    > Example 1:
    > my $this;
    > my $that;
    > foreach $this (@somearray) {
    > foreach $that (@some_other_array) {
    > ........
    > }
    > }
    >
    >
    > Example 2: foreach my $this (@somearray) { foreach my $that
    > (some_other_array) { ....... } }
    IMNSHO you should _always_ put an explicit my() or our() on the
    foreach iterator variable. If you use an existing lexically scoped
    variable then Perl will, in effect, create _another_ lexically scoped
    variable of the same name.

    Your Example 1 is, in fact, interpreted more like:

    my $this;
    my $that;
    foreach my $this (@somearray) {
    foreach my $that (@some_other_array) {
    ........
    }
    }

    IMNSHO Perl should emit a warning when it does this but it doesn't.
    > It seems to me that while the second example does a better job of limiting
    > the scope of variables just to the block in which they're applicable, the
    > second example does cause the construction of a variable each time the outer
    > foreach iterates.
    Yes, that's what most people would intuatively think. That's why I think we need
    a warning.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
    Brian McCauley Guest

  7. #6

    Default Re: Using 'my' within nested loops


    "Brian McCauley" <nobull@mail.com> wrote in message
    news:u9adb6x0y5.fsf@wcl-l.bham.ac.uk...
    > "David Oswald" <spamblock@junkmail.com> writes:
    >
    >
    > Your Example 1 is, in fact, interpreted more like:
    >
    > my $this;
    > my $that;
    > foreach my $this (@somearray) {
    > foreach my $that (@some_other_array) {
    > ........
    > }
    > }
    >
    > IMNSHO Perl should emit a warning when it does this but it doesn't.
    >
    > > It seems to me that while the second example does a better job of
    limiting
    > > the scope of variables just to the block in which they're applicable,
    the
    > > second example does cause the construction of a variable each time the
    outer
    > > foreach iterates.
    >
    > Yes, that's what most people would intuatively think. That's why I think
    we need
    > a warning.
    >
    Thanks, that explains a lot. So would it be accurate to say that the
    majority of the syntaxes that default to $_, are actually (behind the
    scenes) calling something to the effect of my $_, and limiting its scope, or
    is this nuance only applicable to foreach loops?



    David Oswald Guest

  8. #7

    Default Re: Using 'my' within nested loops

    David Oswald <spamblock@junkmail.com> wrote:
    > "Brian McCauley" <nobull@mail.com> wrote in message
    > news:u9adb6x0y5.fsf@wcl-l.bham.ac.uk...
    >> "David Oswald" <spamblock@junkmail.com> writes:
    > So would it be accurate to say that the
    > majority of the syntaxes that default to $_, are actually (behind the
    > scenes) calling something to the effect of my $_,
    ^^^^^

    No.

    my() and local/our() each refer to one of Perl's two systems of
    variables. my() for lexical variables and local/our() for
    package (dynamic) variables.

    Most of Perl's built-in variables are package variables,
    you _cannot_ my() them.

    So, it is a local($_) that foreach gives you.

    > and limiting its scope, or

    Package variables are global variables.

    What you are limiting is not the visibility of the variable, but
    the visibility of the _value_ of the variable.

    You are still open to classic action-at-a-distance bugs, which
    is what happened to you. :-) (or should that be :-(

    > is this nuance only applicable to foreach loops?

    Which nuance?

    Q: The automatic-localling of $_ by foreach?

    A: map and grep do it too.

    Q: the difference between my() and our() variables and values?

    A1: as in the Perl FAQ

    What's the difference between dynamic and lexical (static)
    scoping? Between local() and my()?

    A2: and "Coping with Scoping"

    [url]http://perl.plover.com/FAQs/Namespaces.html[/url]


    A3: Executive summary:

    Always prefer my() variables over our() variables,
    except when you can't.


    (you can get good-old, sane scoping by using a lexical variable
    for foreach's loop control variable: foreach my $str (...)
    )

    --
    Tad McClellan SGML consulting
    [email]tadmc@augustmail.com[/email] Perl programming
    Fort Worth, Texas
    Tad McClellan Guest

  9. #8

    Default Re: Using 'my' within nested loops


    "Tad McClellan" <tadmc@augustmail.com> wrote in message
    <response snipped>

    Thanks again Tad. I appreciate the clarification.

    Dave


    David Oswald Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139