in reply to Re^2: Using import to generate subroutines
in thread Using import to generate subroutines

Although it makes no difference here, in general it's better to write that as
for my $f (@_) { no strict 'refs'; *{"$caller\::$f"} = sub { print "$f\n" }; }
This limits the scope of the no strict 'refs'. Otherwise, if you add any more code after the foreach, it will not be checked with strict.

Replies are listed 'Best First'.
Re^4: Using import to generate subroutines
by revdiablo (Prior) on Nov 24, 2004 at 17:23 UTC

    I put no strict 'refs' outside the loop because I didn't like the idea of running it repeatedly. I doubt it makes much of a difference in terms of performance, but it just didn't feel right in terms of semantics. I only wanted to turn it off once, not N times.

    That said, your concern is valid. Maybe we can reach a compromise:

    sub import { my $class = shift; my $caller = (caller)[0]; { # limit the scope of unstrict refs no strict 'refs'; for my $f (@_) { *{"$caller\::$f"} = sub { print "$f\n" }; } } }

    Update: thanks to fergal for the clarification. I disavow this post. :-)

      strict is a compile time pragma, it's effect is only on how the code in it's scope gets compiled, it doesn't do anything at runtime, so it will only be run once, even inside a loop. Actually now that I think of it any use statement only gets run once no matter where it is.

      Before I realised that it's a use and so has no runtime effect, I did a bit of digging around in strict. The following might interest you.

      If you look at

      > perl -MO=Terse -e 'use strict;my @a;for my $f (@a){no strict "refs"; +print $$f}' LISTOP (0x8225988) leave [1] OP (0x831eec0) enter COP (0x8245398) nextstate OP (0x82258c8) padav [1] COP (0x831ee58) nextstate BINOP (0x831ee30) leaveloop LOOP (0x8232a98) enteriter [2] OP (0x82dc988) null [3] UNOP (0x8232a70) null [141] OP (0x823bc98) pushmark OP (0x823bce8) padav [1] UNOP (0x831ee10) null LOGOP (0x82dc9e8) and OP (0x82dc9a8) iter LISTOP (0x82dc960) lineseq COP (0x823c348) nextstate LISTOP (0x823c300) print OP (0x823c328) pushmark UNOP (0x8225880) rv2sv OP (0x82c1c20) padsv [2] OP (0x82dc9c8) unstack
      you can't see any sign of the no strict 'refs'. It's not in the op tree and therefore doesn't do anything at runtime.

      If you look in more detail and compare the output of

      perl -MO=Debug -e 'use strict;my @a;for my $f (@a){no strict "refs";pr +int $$f}'
      with
      perl -MO=Debug -e 'use strict;my @a;for my $f (@a){print $$f}'
      you will find (amongst other things) that the first contains
      UNOP (0x83085c8) op_next 0x830b190 op_sibling 0x0 op_ppaddr PL_ppaddr[OP_RV2SV] op_targ 0 op_type 15 op_seq 7139 op_flags 6 op_private 1 op_first 0x8309088
      and the second contains
      UNOP (0x982ca28) op_next 0x981f960 op_sibling 0x0 op_ppaddr PL_ppaddr[OP_RV2SV] op_targ 0 op_type 15 op_seq 7128 op_flags 6 op_private 3 op_first 0x9835dd8

      (I am far from an expert on these things by the way) RV2SV means Reference value 2 Scalar Value, this comes from $$f above. If you look in perl.h you'll find

      #define HINT_STRICT_REFS 0x00000002 /* strict pragma */

      This is used to turn on and off a flag in op_private.You can see that in the two debug dumps above, op_private is 1 for the no strict version and 3 for the all strict. This flag tells the interpreter whether the dereference should be checked for strictness when it's run. So here you can see exactly what the compile time effect of strict is.

        This is wrong. Strict subs and vars are compile time but strict refs are handled at runtime. Its used by the dereferencing opcodes so while you don't see an opcode for strict refs itself, it is still used. In fact, it can only be effective at runtime.

        Also, every time you say use ... you run the module's import() method. It happens at compile time but it certainly isn't a once-only thing.

        In regard to revdiablo's concern, the right thing to do is to put it inside the loop. It doesn't exert any additional overhead and definately should be used without having extra, confusing scopes.

        strict is a compile time pragma, it's effect is only on how the code in it's scope gets compiled, it doesn't do anything at runtime

        Ah, indeed. I erroneously thought the lexical effect was also a runtime effect. I stand corrected. Thanks for replying.