in reply to Interpolate variable into regexp at time of definition rather than execution, as a filter for Path::Iterator::Rule

At this point, the variable is no longer valid and could have been overwritten by some other value.

This isn't true.

Resulting errors are many times this line:

And neither is this. You can't get that error from the code you posted.


The code is actually correct. Yes, $int goes out of scope on the last line of the snippet. But that only limits its visibility, not its lifespan. By capturing the lexical, the anon sub extends its life.

Even if the code is called in a loop, everything will work. A new $int will be created. This is easy to demonstrate:

my @subs; for (qw( 123 456 789 )) { my $int = $_; push @subs, sub { $int }; } say $_->() for @subs;
123 456 789

In contrast, note how the following code only has one $int that's captured three times:

my $int; my @subs; for (qw( 123 456 789 )) { $int = $_; push @subs, sub { $int }; } say $_->() for @subs;
789 789 789

Maybe you didn't use a properly-scoped lexical variable?

I could have used for my $int in the first snippet, but I wanted to make the two snippets easier to contrast.

  • Comment on Re: Interpolate variable into regexp at time of definition rather than execution, as a filter for Path::Iterator::Rule
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Interpolate variable into regexp at time of definition rather than execution, as a filter for Path::Iterator::Rule
by ecm (Novice) on Apr 28, 2026 at 15:03 UTC

    Thank you, it was indeed an error on my part. I originally used $1 in the filter's regexp which does generate a similar error message (that was part of what misled me later). I also pruned a test case now so there aren't thousands of error messages confusing things (which also misled me). For the test case I deleted all but 4 content files (20, 21.5800, 21.5802, 22), then compiled that to get a much smaller list file. And I found a way to run the filter from a command-line interface rather than my application's TUI. I uploaded all the test case files to our server.

    Here's the nonworking code without a named variable, just using $1:

    test$ grep '#/INT' dir1list.pl -A1 -B3 } my $rule = Path::Iterator::Rule->new; if ($id =~ /^([0-9A-F]{2})/) { $rule->and( sub { m#/INT $1# } ); }

    And here's the output, as expected except for the "Use of uninitialized value $1 in regexp compilation" lines and the fact that "Searching file INT 20 DOS 1 TERMINATE PROGRAM.txt" is displayed. (The filter is intended to avoid this scan specifically, as the unique ID indicates that we only want to search pathnames matching "/INT 21".)

    test$ ./dir1list.pl --listing TheList/INTERRUP.LST --source source --f +ind --summary --link 21.58 From "[Link command line switch]": Hyperlink selected: INT 21/AH=58h Found: "INT 21 - DOS 2.11+ - GET OR SET MEMORY ALLOCATION STRATEGY (AH +=58h/AL=00h,01h)" Use of uninitialized value $1 in regexp compilation at ./dir1list.pl l +ine 1166, <$array_lstff[...]> line 125. Searching file INT 20 DOS 1 TERMINATE PROGRAM.txt Use of uninitialized value $1 in regexp compilation at ./dir1list.pl l +ine 1166. Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 211 GET O +R SET MEMORY ALLOCATION STRATEGY.txt Found: "INT 21 - DOS 5+ - GET OR SET UMB LINK STATE (AH=58h/AL=02h,03h +)" Use of uninitialized value $1 in regexp compilation at ./dir1list.pl l +ine 1166, <$array_lstff[...]> line 323. Searching file INT 20 DOS 1 TERMINATE PROGRAM.txt Use of uninitialized value $1 in regexp compilation at ./dir1list.pl l +ine 1166. Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt Use of uninitialized value $1 in regexp compilation at ./dir1list.pl l +ine 1166. Searching file INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR +SET UMB LINK STATE.txt

    And here's what I reconstructed from my editor as the wrong code I tried, note the minus sign instead of equals sign:

    test$ grep '#/INT' minuslst.pl -A1 -B3 my $rule = Path::Iterator::Rule->new; if ($id =~ /^([0-9A-F]{2})/) { my $int - $1; $rule->and( sub { m#/INT $int# } ); }

    Here's what this runs like. Note the error messages, including some I didn't notice previously reading "Useless use of subtraction (-) in void context at ./minuslst.pl line 1166." and "Use of uninitialized value $int in subtraction (-) at ./minuslst.pl line 1166, <$array_lstff...> line 125." (It is unfortunate that the subtraction like that only warrants an error at run time and doesn't cause perl to refuse to run the program. I do of course have "use warnings;" and "use strict;" already.) After that the error message that I previously quoted appears multiple times, and the INT 20 file is also searched again.

    test$ ./minuslst.pl --listing TheList/INTERRUP.LST --source source --f +ind --summary --link 21.58 Useless use of subtraction (-) in void context at ./minuslst.pl line 1 +166. From "[Link command line switch]": Hyperlink selected: INT 21/AH=58h Found: "INT 21 - DOS 2.11+ - GET OR SET MEMORY ALLOCATION STRATEGY (AH +=58h/AL=00h,01h)" Use of uninitialized value $int in subtraction (-) at ./minuslst.pl li +ne 1166, <$array_lstff[...]> line 125. Use of uninitialized value $int in regexp compilation at ./minuslst.pl + line 1167, <$array_lstff[...]> line 125. Searching file INT 20 DOS 1 TERMINATE PROGRAM.txt Use of uninitialized value $int in regexp compilation at ./minuslst.pl + line 1167. Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 211 GET O +R SET MEMORY ALLOCATION STRATEGY.txt Found: "INT 21 - DOS 5+ - GET OR SET UMB LINK STATE (AH=58h/AL=02h,03h +)" Use of uninitialized value $int in subtraction (-) at ./minuslst.pl li +ne 1166, <$array_lstff[...]> line 323. Use of uninitialized value $int in regexp compilation at ./minuslst.pl + line 1167, <$array_lstff[...]> line 323. Searching file INT 20 DOS 1 TERMINATE PROGRAM.txt Use of uninitialized value $int in regexp compilation at ./minuslst.pl + line 1167. Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt Use of uninitialized value $int in regexp compilation at ./minuslst.pl + line 1167. Searching file INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR +SET UMB LINK STATE.txt

    Finally, the correct code that I intended to try before:

    test$ grep '#/INT' dirlist.pl -A1 -B3 my $rule = Path::Iterator::Rule->new; if ($id =~ /^([0-9A-F]{2})/) { my $int = $1; $rule->and( sub { m#/INT $int# } ); }

    As you suggested, this actually works just fine. The run shows no more error messages and the INT 20 and INT 22 files aren't searched, as intended:

    test$ ./dirlist.pl --listing TheList/INTERRUP.LST --source source --fi +nd --summary --link 21.58 From "[Link command line switch]": Hyperlink selected: INT 21/AH=58h Found: "INT 21 - DOS 2.11+ - GET OR SET MEMORY ALLOCATION STRATEGY (AH +=58h/AL=00h,01h)" Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 211 GET O +R SET MEMORY ALLOCATION STRATEGY.txt Found: "INT 21 - DOS 5+ - GET OR SET UMB LINK STATE (AH=58h/AL=02h,03h +)" Searching file INT 2158 DOS 211 GET OR SET MEMORY ALLOCATION STRATEGY. +txt Searching file INT 2158 DOS 5 GET OR SET UMB LINK STATE.txt source/Interrupt List/INT 21 DOS Function Calls/INT 2158 DOS 5 GET OR +SET UMB LINK STATE.txt test$
      So the TL;DR version is you wrote
      • my $int - $1;
      instead of
      • my $int = $1;
      and didn't notice the warnings. ;-)

      > (It is unfortunate that the subtraction like that only warrants an error at run time and doesn't cause perl to refuse to run the program. I do of course have "use warnings;" and "use strict;" already.)

      you can always turn warnings fatal to make Perl die on the spot.

      ~$ perl -e'use warnings FATAL=>"all"; my $x-1; print "never executed"' Useless use of subtraction (-) in void context at -e line 1. ~$

      (use FATAL => "void" to only "fatalize" this particular warning class, see perldiag ° )

      That's a good strategy for unit tests anyway where unexpected warnings shouldn't appear. Not sure if I'd like to have this in much longer, hence messier production code.

      You can probably also apply Perl::Critic or another linter for this to happen statically at compile time.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

      footnote

      °) one reason this might not warn at compile time is that you still have a "side effect" in the declaration of my $int - hence this could be intended code (?)

      update

      I think an optional pragma to make some warning classes die at compile time is worth a consideration.