develooper Front page | perl.perl5.porters | Postings from February 2018

Re: Why does inclusion of require that is not executed have sideeffects?

Thread Previous | Thread Next
From:
demerphq
Date:
February 25, 2018 03:05
Subject:
Re: Why does inclusion of require that is not executed have sideeffects?
Message ID:
CANgJU+Un9Tknk+M+ZytPPm_CiVh6wR__Gn4caemw-Bp_gFBp=g@mail.gmail.com
On 24 February 2018 at 23:18, Sawyer X <xsawyerx@gmail.com> wrote:
>
>
> On 02/23/2018 07:45 PM, Karl Williamson wrote:
>> On 02/23/2018 10:27 AM, Eirik Berg Hanssen wrote:
>>> On Fri, Feb 23, 2018 at 6:06 PM, Dagfinn Ilmari Mannsåker
>>> <ilmari@ilmari.org <mailto:ilmari@ilmari.org>> wrote:
>>>
>>>     demerphq <demerphq@gmail.com <mailto:demerphq@gmail.com>> writes:
>>>     > Why would a require that is not executed have any side effects?
>>> Why is
>>>     > the eval necessary to avoid those side effects? Is this a bug
>>> or have
>>>     > I missed something?
>>>
>>>     As haarg pointed out on #p5p, merely compiling a 'require BAREWORD'
>>>     creates the package.  A bit of digging leads to a
>>>     gv_stashpvn(…, GV_ADD|…) call in toke.c, and some more digging
>>> with git
>>>     blame shows that this was added in 5.001, with the following Changes
>>>     entry:
>>>
>>>     NETaa13235: require BAREWORD now introduces package name
>>> immediately.
>>>     From: Larry Wall
>>>     Files patched: toke.c
>>>       require BAREWORD now introduces package name immediately.  This
>>>     lets the
>>>       method intuit code work right even though the require hasn't
>>>     actually run
>>>       yet.
>>>
>>>     So it's a deliberate desicion by Larry in 1995 to make indirect
>>> method
>>>     syntax work better with require (as opposed to use).
>>>
>>>
>>>    Nice sleuthing.
>>>
>>>    Now, I do find myself wondering if C<< perldoc -f require >>
>>> should document this compile time effect?
>>>
>>>    I mean, I doubt it could be called an implementation detail likely
>>> to change, but neither do I imagine most programmers would ever need
>>> to know, so ... I dunno, what does the documentation aspire to be?
>>>
>>>
>>> Eirik
>>
>> Given how much unnecessary work was required to find this now, I think
>> it should be documented.
>
> +1.

commit af596f2c321249499f853ae4af57570ef48640d9
Author: Yves Orton <demerphq@gmail.com>
Date:   Sun Feb 25 04:04:02 2018 +0100

    explain compile time effects of require

    there is a difference between

       require Foo::Bar;

    and

       require "Foo/Bar.pm";

    in that the former will autovivify the Foo::Bar namespace at compile
    time, but the latter will not. Populating the namespace is left to run
    time in both cases.

    This doc adds some details about this to the require entry in perlfunc

diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index ce989b0..6b04a0c 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -6503,14 +6503,16 @@ statements.
 If EXPR is a bareword, L<C<require>|/require VERSION> assumes a F<.pm>
 extension and replaces C<::> with C</> in the filename for you,
 to make it easy to load standard modules.  This form of loading of
-modules does not risk altering your namespace.
+modules does not risk altering your namespace, however it will autovivify
+the stash for the required module.

 In other words, if you try this:

         require Foo::Bar;     # a splendid bareword

 The require function will actually look for the F<Foo/Bar.pm> file in the
-directories specified in the L<C<@INC>|perlvar/@INC> array.
+directories specified in the L<C<@INC>|perlvar/@INC> array, and it will
+autovivify the C<Foo::Bar::> stash at compile time.

 But if you try this:

@@ -6525,12 +6527,20 @@ will complain about not finding F<Foo::Bar>
there.  In this case you can do:

         eval "require $class";

+or you could do
+
+        require "Foo/Bar.pm";
+
+Neither of these forms will autovivify any stashes at compile time and
+only have run time effects.
+
 Now that you understand how L<C<require>|/require VERSION> looks for
 files with a bareword argument, there is a little extra functionality
 going on behind the scenes.  Before L<C<require>|/require VERSION> looks
 for a F<.pm> extension, it will first look for a similar filename with a
 F<.pmc> extension.  If this file is found, it will be loaded in place of
-any file ending in a F<.pm> extension.
+any file ending in a F<.pm> extension. This applies to both the explicit
+C<require "Foo/Bar.pm";> form and the C<require Foo::Bar;> form.

 You can also insert hooks into the import facility by putting Perl code
 directly into the L<C<@INC>|perlvar/@INC> array.  There are three forms

-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About