http://www.perlmonks.org?node_id=935352

Sewi has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

just found a piece of suspicious source:

use strict; [...] sub foo { no strict 'refs'; my $delete = &$routine_name($row, $nrow, $tablename); use strict 'refs'; }

Does "strict" really work this way? I'd assume that one "no strict refs" within the whole file disables strict refs for the whole file and this block seems to work but doesn't really do what one might think when reading this source.

Thanks

Replies are listed 'Best First'.
Re: no strict refs for blocks?
by choroba (Cardinal) on Nov 02, 2011 at 11:17 UTC

      Thank you, this is the link I didn't find earlier.

      The "no strict refs" is valid, but the additional "use strict refs" is a NOOP.

        but the additional "use strict refs" is a NOOP.
        Actually, it would reenable strict for any code below in the remainder of the block. Here it is indeed not doing anything. Probably the person who wrote this snippet copy/pasted it from somewhere else without knowing why the "use strict" was there (typically known in the Perl world as "cargo culting"); or else, there might have been some code below it, which got deleted, and this just stuck.
Re: no strict refs for blocks?
by ikegami (Patriarch) on Nov 02, 2011 at 19:26 UTC

    [ This post gives some of the technical details in case someone is interested. ]

    Not only does it work, a fair amount of effort went into making it work.

    use strict; and no strict; are executed at compile-time, yet the "refs" check is a run-time check. This is done by attaching hints to some opcodes (the same opcodes that provides line numbers for warnings and such, I think). Telling the parser which hints to use is done via $^H. Peeking at the hints in effect can be done using caller.

    The hints are lexically scoped in the parser in order to make the effects of this pragma lexically scoped too.

    $ perl -E' my @hints = ( [refs=>0x2], [subs=>0x200], [vars=>0x400] ); sub hints { my $h = (caller(0))[8]; my @h = map { $h & $_->[1] ? $_->[0] : () } @hints; @h ? join(",", @h) : "[none]" } say hints; # [none] use strict; say hints; # refs,subs,vars { say hints; # refs,subs,vars no strict; say hints; # [none] } say hints; # refs,subs,vars ' [none] refs,subs,vars refs,subs,vars [none] refs,subs,vars

      This is done by attacking hints to some opcodes

      With sticks or stones?

        Fixed
Re: no strict refs for blocks?
by moritz (Cardinal) on Nov 02, 2011 at 11:13 UTC

    The use strict 'refs'; is unneeded, because strict. Apart from that, it seems to do what you want: when strict refs are disabled, &$routine_name() calls the sub with name $routine_name:

    $ perl -Mstrict -wE 'sub f { say "f" }; my $x = "f"; { no strict "refs +"; &$x() }; &$x()' f Can't use string ("f") as a subroutine ref while "strict refs" in use +at -e line 1.