in reply to Re^2: Perl 28 broke L: How to fix?
in thread Perl 28 broke L: How to fix?

The eval is because the regexp might match a package name but you don't have a module with that name available to be loaded. For example, if "lib/Foo.pm" defines a function called "Foo::Bar::baz", then you run this:

perl -Ilib -MFoo -ML -e'Foo::Bar::baz(42)'

… without the eval it will die because "lib/Foo/Bar.pm" doesn't exist, even though "lib/Foo/Bar.pm" is unnecessary because "Foo::Bar::baz" is defined elsewhere in a module that successfully loaded.

Replies are listed 'Best First'.
Re^4: Perl 28 broke L: How to fix?
by Anonymous Monk on Nov 03, 2019 at 08:00 UTC
    The eval is because the regexp might match a package name

    I knew there was a reason like that but was puzzled when it worked without eval. Thanks for explaining. I forget to load modules and -ML is less punishment so you can imagine how much I like L! I wonder why Perl doesn't use the failure to load a method or function, because the module isn't loaded, as an opportunity to look for it and load it. For example:

    perl -e 'Foo->bar'
    Can't locate object method "bar" via package "Foo" (perhaps you forgot to load "Foo"?) at -e line 1. (Perhaps Perl, or perhaps *you* forgot to load "Foo" so object method "bar" can be located? ;-)
    perl -e 'print qq~package Foo; sub bar { print "baz\\n" } 1\n~' > Foo. +pm; cat Foo.pm
    package Foo; sub bar { print "baz\n" } 1
    perl -I. -MFoo -e 'Foo->bar'
    baz
    perl -I. -ML -e 'Foo->bar'
    baz
    I can hack away -M Perl, to locate object method "bar" via package "Foo", why wont you?!
    perl -I. -e 'eval{Foo->bar};$_=$@;s/.*forgot to load "([^"]+)".*/$1/s; +eval{require"$_.pm"};Foo->bar'
    baz
    And minimize L, to see what's happening, to X.pm:
    perl -e 'print qq~package X; { package UNIVERSAL; our \$AUTOLOAD; sub +AUTOLOAD { warn "\$AUTOLOAD" }} 9\n~' > X.pm; cat X.pm
    package X; { package UNIVERSAL; our $AUTOLOAD; sub AUTOLOAD { warn "$AUTOLOAD" }} 9
    perl -I. -MX -e ''
    I don't know what this means:
    IO::File::DESTROY at X.pm line 1.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    
    But this!
    perl -I. -MX -e 'Foo->bar'
    Yes
    IO::File::DESTROY at X.pm line 1.
    Foo::bar at X.pm line 1.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    IO::File::DESTROY at X.pm line 1 during global destruction.
    
    I know what line 2 means! Perl knows what it means. Why doesn't she connect the dots automatically? I guess it would lead to all sorts of chaos and... L! Is L searching @INC in the background with Module::Load to find Foo.pm (and say Bar->foo that doesn't exist), and that's somehow dangerous (according to L docs)?

      "I wonder why Perl doesn't use the failure to load a method or function, because the module isn't loaded, as an opportunity to look for it and load it."

      Very few languages will automatically attempt to load a class/package/module when you try to use one which isn't defined yet. Off the top of my head, I can only think of one that will — PHP, and it doesn't do so by default.

      With Perl, such a feature might cause unexpected behaviour sometimes. For example:

      local $Data::Dumper::Indent = 1; print Data::Dumper::Dumper($thing);

      If calling Data::Dumper::Dumper() autoloaded Data::Dumper, then the autoloading would set $Data::Dumper::Indent to 2 (see the source of Dumper.pm for why) so you'd get the wrong indentation.

      These kinds of bugs would probably be pretty hard to track down. Load order bugs are tricky enough to figure out already when the order modules are loaded can be seen pretty clearly in the source code; adding in autoloading would make things even worse.

      While -ML is pretty handy for one-liners, having that feature enabled in anything bigger could be a nightmare.