On Fri, 14 Apr 2023 at 21:14, Tomasz Konojacki <me@xenu.pl> wrote:
>
> On Fri, 14 Apr 2023 21:11:22 +0200
> Tomasz Konojacki <me@xenu.pl> wrote:
>
> > There's an open PR that adds a warning in this case:
> >
> > https://github.com/Perl/perl5/pull/19419
>
> Actually, this warns only when import has arguments. So,
> "use Client::Db 'foo'" would warn, but "use Client::Db" would not.
The problem is that it is perfectly legit to have a package whose name
on disk does not match the package it installs functionality into. A
common pattern for instance is to have a file Whatever/Heavy.pm load
functionality that gets installed into the Whatever namespace instead
of into the Whatever::Heavy namespace. (using a file may populate zero
or many namespaces so there is no way to validate it is functioning as
intended). These days we dont have any examples of this in core that
I am aware of, but historically Carp::Heavy and Exporter::Heavy were
good examples of this pattern. We do have examples in core where
certain namespaces are populated as a side-effect of loading a
specific file. Tie::Hash for instance populates the namespaces
Tie::Hash, Tie::StdHash, Tie::ExtraHash.
We can validate if there was a typo when someone asks the newly loaded
package to export a symbol because if there is a mistake then
execution will end up inside of UNIVERSAL::import() instead of the
import method in the loaded package that should be handling the
export. But when there is nothing to export we cannot distinguish
between someone playing presumably legitimate games with package names
and file names and someone making a typo on the filename. After all
people regularly load modules with 'use' that do not contain an import
method, do not use Exporter or any hand rolled equivalents, and do not
export anything.
The fact that the filesystem's case insensitivity plays a role here
just makes things worse. Eg, you say "use Client::db;" the case
insensitivity "corrects" your mistake and loads "Client/Db.pm" but you
still think it should be called Client::db when in fact it is called
Client::Db. Another factor that also makes things worse is that we
dont have a standard built in way of exporting functionality, and we
have a proliferation of modules that implement "exporter" semantics.
So we can't "just" introduce a solution to these problems in the
standard modules like Exporter.pm. [. This came up previously with this
PR and related subject. ] We either have to figure out tricky
solutions really low down the stack (eg, the trickery in Universal,
and the trickery in core itself to not error when import is missing),
or we have to leave the bug. [.ASIDE: I consider the way Perl handles
symbol imports to be in the list of Larrys top 10 design mistakes for
Perl, it is a place where TIMTOWTDI is a very bad idea and has caused
huge trouble IMO - seems nice at first, but on further reflection
causes a world of trouble.]
Anyway, that PR was stalled for various reasons, thanks for the
reminder. Ill try to get it picked up in the 5.39 dev cycle.
Interesting piece of trivia: The "import" method is handled via a
special case, so you can call it on any package or namespace and it
will not throw an exception if it is missing. The PR you linked to
fixes that so that the import method is treated as any other function,
and then ensures that UNIVERSAL::import() exists to handle any calls
to packages that do not implement import().
cheers,
Yves
--
perl -Mre=debug -e "/just|another|perl|hacker/"