Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using strict with an empty list equivalent to not using strict at all?

Tags:

perl

TLDR: See question title.

In the original version of a question, there was use strict (); at the top of the program. No variables were declared with my. The program worked. I pointed that out that the code wouldn't work because of the missing mys, but it turns out I was mistaken.

$ perl e 'use strict (); $foo = 1'

This program works. It doesn't crash. But obviously this crashes:

$ perl -e 'use strict; $foo = 1'
Global symbol "$foo" requires explicit package name (did you forget to declare "my $foo"?) at -e line 1.
Execution of -e aborted due to compilation errors.

My first idea was to deparse it to see if something else is going on.

$ perl -MO=Deparse -e 'use strict (); $foo = 1'
use strict ();
$foo = 1;
-e syntax OK

But it's not. Then it got me thinking, you can do use strict 'vars', which only turns on the vars thing1. It obviously does that by calling import.

The use strict is the same as BEGIN { require strict; strict->import; }, so the same rule that goes for modules should apply for pragmata too. If I do use Foo (), nothing is imported. Hence, use strict (); should be the same as require strict;, just at run time, because nothing is imported.

$ perl -e 'require strict; $foo = 1'

This doesn't crash. But then at runtime you cannot turn on stuff that is supposed to be set at compile time.

So what does this actually do? When Perl reaches my actual code, it probably already encountered the strict pragma somewhere else, so it wouldn't load it again. And it doesn't import anything.

$ perl -e 'print %INC'

Oops. This prints nothing. %INC is empty. But if we use another module, there is something in it.

$ perl -MData::Dumper -e 'print Dumper \%INC'
$VAR1 = {
          'warnings.pm' => '/usr/share/perl/5.22/warnings.pm',
          'overload.pm' => '/usr/share/perl/5.22/overload.pm',
          'Carp.pm' => '/usr/share/perl/5.22/Carp.pm',
          'strict.pm' => '/usr/share/perl/5.22/strict.pm',
          'overloading.pm' => '/usr/share/perl/5.22/overloading.pm',
          'constant.pm' => '/usr/share/perl/5.22/constant.pm',
          'bytes.pm' => '/usr/share/perl/5.22/bytes.pm',
          'Data/Dumper.pm' => '/usr/lib/x86_64-linux-gnu/perl/5.22/Data/Dumper.pm',
          'XSLoader.pm' => '/usr/share/perl/5.22/XSLoader.pm',
          'Exporter.pm' => '/usr/share/perl/5.22/Exporter.pm',
          'warnings/register.pm' => '/usr/share/perl/5.22/warnings/register.pm'
        };

If we load Data::Dumper, strict was loaded at some point. But not in the pure -e example.

$ perl -e 'use strict (); print %INC'
strict.pm/usr/share/perl/5.22/strict.pm

Ok. This loads strict.pm.

$ perl -e 'require strict; print %INC'
strict.pm/usr/share/perl/5.22/strict.pm

So does that. But still, none of the strict things are enabled.

So the question really is, is use strict () equivalent to just not having a use strict statement at all, or is there something else happening?


1) perldoc strict refers to the three different arguments strict can take as things

like image 459
simbabque Avatar asked Nov 03 '16 12:11

simbabque


1 Answers

use strict ();

(essentially) doesn't do anything: see the docs:

If you do not want to call the package's import method (for instance, to stop your namespace from being altered), explicitly supply the empty list:

use Module ();

That is exactly equivalent to

BEGIN { require Module }

Of course, strict only does something if you call its import method (which you can easily verify by reading its source code; it's only about 150 lines long). So bypassing the import method bypasses the entire effect of use strict.

like image 103
Jonathan Cast Avatar answered Oct 21 '22 10:10

Jonathan Cast