in reply to Strictly nested sub warnings

The problem is I get a warning that says:

Variable "@SymLinks" will not stay shared at ./test.pl line 21.

Did you look up the warning in perldiag? If so, which part isn't clear? If not, you should.

Replies are listed 'Best First'.
Re^2: Strictly nested sub warnings
by raybies (Chaplain) on Oct 05, 2010 at 14:33 UTC

    Thanks. I found more info about the warning...

    Curious, but is perldiag a program or part of the built-in help? Cuz when I type perldiag at the linux prompt it does nothing.

    I googled perldiag, and found this page, that helped me understand that I need to create the sub anonymously, that way it's created at runtime, rather than at compile time...

    SO, fwiw, I was able to fix my warning by assigning the nested function named inlineFind to a variable anonymously like the following:

    #!/usr/bin/perl use strict; use warnings; use File::Find; sub SymLinkFind($); my %params; $params{recurseDir} = "."; SymLinkFind(\%params); print "Found ", $params{numoLinks}, " Symbolic Links...\n"; sub SymLinkFind($) { my $reparams = shift; my @SymLinks; my $subhold = sub { #<--this line changed my $namey = $File::Find::name; if (-l) { push @SymLinks, $namey; } }; #<--remember ; to complete variable assign find $subhold, $reparams->{recurseDir}; # <--use variable instead of + named function. $reparams->{Links} = \@SymLinks; $reparams->{numoLinks} = scalar(@SymLinks); return; }

    And that got rid of the warning. So is there any great impact on the performance of this, if it is compiled at runtime? I didn't see any in running my simple example.

    Thanks,

    --Ray

      It's one of the documentation pages.

      man perldiag perldoc perldiag perl -Mdiagnostics script.pl

      perldiag

      Nested named subs are not supported by Perl. For starters, the nested sub wouldn't be private. Secondly, you'll get weird errors. (You're notified if the second can happen by "will not stay shared" warnings.)

        Thanks! That -M diagnostic trick is great. --Ray
      So is there any great impact on the performance of this, if it is compiled at runtime?

      It's compiled at compile time just like a named function. You get a new version of it every time you execute the code (so it can bind to an enclosing lexical scope), but the actual opcodes Perl 5 executes within the body of the function stay as they are.

      You seem to be writing Perl in an idiosyncratic, verbose, almost baroque, style. To do something very simple, namely find all symbolic links under a given directory, you've got a lot of scaffolding. Perhaps the code has been taken out of context, but I feel your "input-output" parameter hash serves only to obscure the intent of the function. Good functions have few, and clearly specified, input and output. Since Perl arrays already know how many elements they contain, storing the number of elements in a separate numoLinks attribute is redundant and a violation of DRY. Anyway, FWIW, I present a shorter, more Perlish version of your subroutine:

      use strict; use warnings; use File::Find; # Return a list of all symlinks found under $dir. sub SymLinkFind { my $dir = shift; my @SymLinks; find sub { -l and push @SymLinks, $File::Find::name }, $dir; return @SymLinks; } my @symlinks = SymLinkFind("."); print "Found ", scalar(@symlinks), " Symbolic Links...\n"; print "$_\n" for @symlinks;

        you're absolutely right about the numolinks, thing.

        Though the reason it has all this scaffolding is due to the fact that the actual inlineFind function I wrote was about ten times more complex (looking for more than just symbolic links, but all sorts of different files and throwing them into an assortment of lists). So I just sorta shortened it to the symbolic link to demonstrate the warning I was getting.

        I do appreciate the pointers, however. The great thing about Perl is I can use it for years and years, and still learn a ton everyday I use it.

        Also, I admit sometimes I am a C coder at heart... well, that and I once taught assembler at a university.

        We all bear our scars. Heh.

      Curious, but is perldiag a program or part of the built-in help? Cuz when I type perldiag at the linux prompt it does nothing.
      Neither. Perl does not come with built-in help. Instead, perl comes with a gazillion manual pages - each of them listed in the perl manual page.

      You have typed man perl from your Linux prompt at least once, didn't you?

        ...maaaay-bee... :) I'm clearly not in the habit of using it. SO thanks!

        The whole use strict/warnings stuff is relatively new to me. I've used Perl for over ten years, but never bothered with doing it right... Heh. (pathetic, I know)

        Now I'm seeing how these checks can be useful...