Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Re^3: How to import "global" variables into sub-scripts from main script?

by jcb (Parson)
on Mar 23, 2021 at 21:20 UTC ( [id://11130241] : note . print w/replies, xml ) Need Help??

in reply to Re^2: How to import "global" variables into sub-scripts from main script?
in thread How to import "global" variables into sub-scripts from main script?

Developing with strict and then removing it should have no effect at runtime, but you would likely be better served using a persistent execution environment or ByteLoader then by worrying about the relatively small parsing overhead of use strict; and our.

The important feature that strict 'vars' provides is that it enforces declaration of variables, which will catch typos. If you mistype if $DEBUG as if $DEGUB, strict 'vars' will cause an error, while running without strict will cause Perl to silently create a "$DEGUB" variable with an initial undefined value.

Lastly, while our is equivalent to simply running without strict in terms of making global (package) variables available, my actually does alter the semantics of the program. The only bloat you will get from strict is use strict; itself and any use vars or our declarations — all other variable declarations are actually important.

Replies are listed 'Best First'.
Re^4: How to import "global" variables into sub-scripts from main script?
by choroba (Cardinal) on Mar 23, 2021 at 21:36 UTC

      This is Perl, of course it's possible to construct a counterexample ;-) Imagine someone wrote their own version of Data::Diver:

      use warnings; use strict; sub dive { my ($data, @path) = @_; die "unsafe keys" if grep { /[^a-zA-Z0-9_]/ } @path; return eval '$data->'.join('', map { "{$_}" } @path); } use Test::More tests=>6; sub exception (&) { eval { shift->(); 1 } ? undef : ($@ || die) } our %quz = ( quz => 'Hello!' ); our %foo = ( bar => 'quz', baz => { hello => "World!" } ); is dive(\%quz, qw/ quz /), 'Hello!'; is dive(\%foo, qw/ bar /), 'quz'; is dive(\%foo, qw/ bar x /), undef; is dive(\%foo, qw/ baz hello /), 'World!'; is dive(\%foo, qw/ bar quz /), undef; like exception { dive(\%foo, qw/ $hello /) }, qr/\bunsafe keys\b/i;

      Under no strict 'refs', the code will behave differently and the tests will fail.

      Any code with eval is susceptible - for a slightly more realistic scenario, imagine a templating system that is loading data from JSON, for example. Update: Though I think the code above isn't even that unrealistic, given the huge number of modules on CPAN there's bound to be one or two that do something like that. Also added a test case to the above code.

      That's an interesting idea.

      This example dies under strict with Can't use string as a HASH ref and would "survive" with faulty magic after strict was removed.

      For this not to be noticed under strict the symbolic ref has only to happen occasionally.

      So yes it has an effect on runtime, but this is "only" exchanging one (fatal) bug with a weird bug in edge cases.

      So what could happen is that someone thought removing strict fixed the bug in a long running script, which eventually produced broken data.

      Well ... I think we agree that removing strict is not a good idea anyway.

      One might only be able to make a case for short scripts and one-liners. But the longer you wait to activate strict the more expensive it gets.

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

      Assuming that all code paths are actually exercised in development/testing with strict in effect, I would expect a testing cycle to prove that the program is type-safe with respect to hard-references/other-data, such that symbolic references could not be encountered at runtime that were not seen in testing. This requires that the tests are actually thorough and near-exhaustive.

      For our questioner, that is a very large assumption and I would not be surprised to find that the code that produced this question has no testsuite.

      In terms of runtime performance, I doubt that strict 'refs' has any effect at all: perl must check for symbolic references in any case as it can never assume that a dereferenced value will actually be a reference and the only difference is whether a possible symbolic reference is considered or an error immediately thrown when dereferencing something other than a hard reference.