为什么Perl说我只使用一次?为什么这是一个问题?

时间:2022-03-08 05:28:02

I have some code that I've managed to narrow down to the following smallest-code sample.

我有一些代码可以缩小到下面的smallest代码示例。

First I have a module plugh.pm which is responsible for reading in a configuration file. The meat of this can basically be replaced with the following, which sets up one configuration item:

首先我有一个模块plugh。在配置文件中负责读取的pm。这部分的肉基本上可以用下面的方法替换,它设置了一个配置项:

use strict;
use warnings;
sub cfgRead () { $main::cfg{"abc"} = "/usr"; }
1;

Then I have a main program which uses that module as follows, simply calling the function to set up configuration items, then using one of those items in a subroutine:

然后我有一个主程序,它使用这个模块,简单地调用函数来设置配置项,然后在子例程中使用其中的一个项:

#!/usr/bin/env perl

use strict;
use warnings;
use 5.005;

require File::Basename;
import File::Basename "dirname";
push (@INC, dirname ($0));
require plugh;

my (%cfg);

sub subOne () {
        my $list = `ls -1 $main::cfg{"abc"}`;
        my @list = split (/\s+/, $list);
        my $fspec;
        foreach $fspec (@list) {
                print $fspec . "\n";
        }
}

sub mainLine () {
        cfgRead();
        subOne();
}

mainLine();

Now, when I run this, I get the following output with the first line being standard error and the rest being standard output:

现在,当我运行这个时,我得到如下输出,第一行是标准错误,其余的是标准输出:

Name "main::cfg" used only once: possible typo at /home/xyzzy/bin/xyzzy line 15.
bin
games
include
lib
lib64
local
sbin
share
src

The line it's complaining about is the ls -1 subprocess creation. My question is simply: so what? Yes, I only use it once but why is that even an issue?

它抱怨的是ls -1子进程的创建。我的问题很简单:那又怎样?是的,我只使用一次,但为什么这是一个问题呢?

If I was never using it, then fine, but I can't see why Perl is warning me about only using it once.

如果我从来没有使用过它,那么很好,但是我不明白为什么Perl只警告我一次使用它。

I get the variable from the associative array and then use it to get a directory listing. Is there some sort of bizarre Perl guideline that states variables have to be used at least twice? Seven times? Forty-two? I'm seriously stumped.

我从关联数组中获取变量,然后使用它来获得一个目录列表。是否存在某种奇怪的Perl准则,说明变量必须至少使用两次?七次吗?42吗?我真的难住了。

3 个解决方案

#1


9  

There are a few odd things here.

这里有一些奇怪的东西。

First: when you have use strict active, you will get a warning if you use a variable without declaring it, or referencing it by fully qualified name.

首先:当您使用严格的活动时,您将得到一个警告,如果您使用一个变量而不声明它,或者以完全限定的名称引用它。

What you have actually done is to declare a local %cfg with my() in xyzzy.pl, and then to reference a different, package-global variable %main::cfg (implicitly declared by using its fully qualified name).

实际上,您所做的是在xyzzy中使用my()来声明一个本地%cfg。然后引用一个不同的包全局变量%main::cfg(通过使用它的完全限定名来隐式声明)。

To make the reference link to the same %cfg that you declared, you should declare it our() to make it package-global. Then you can either reference it as $main::cfg{} in both places (or just $cfg{} from xyzzy.pl), or else you can declare it our() in plugh.pm as well (so that you can use the bare %cfg in both places).

为了使引用链接到您声明的相同的%cfg,您应该声明我们()使其成为包全局的。然后,您可以将其作为$main::cfg{}在两个位置(或仅从xyzzy.pl中获得$cfg{}),或者您可以在plugh中声明我们的()。pm也可以(这样你可以在两个地方使用光%cfg)。

The odd thing is that you do have two references to that variable, so you shouldn't get the warning. I think what has happened here is that the implicit declarations in two separate files are assumed to be separate variables.

奇怪的是,你确实有两个对那个变量的引用,所以你不应该得到警告。我认为这里发生的情况是,两个独立文件中的隐式声明被假定为单独的变量。

xyzzy.pl:

xyzzy.pl:

require plugh;

our (%cfg);

sub subOne () {
   my $list = `ls -1 $cfg{"abc"}`;
   ...
}

plugh.pm:

plugh.pm:

our(%cfg);
sub cfgRead () { $cfg{"abc"} = "/usr"; }

#2


12  

I think your original question is answered, so I'll just pass along my advice. Don't ever use globals if you can avoid it. You are using subroutines as mere clusters of code and not passing them any arguments, and that's where your problems come from.

我认为你最初的问题得到了回答,所以我就把我的建议转达给你。如果可以避免使用全局变量,请不要使用全局变量。您使用子例程仅仅是代码的集群,并没有传递任何参数,这就是您的问题的来源。

Module:

模块:

sub cfgRead {
    my %cfg;
    $cfg{"abc"} = "/usr";
    ...
    return \%cfg;
}

Main:

主要:

sub subOne {
    my $cfg = shift;
    my $list = `ls -1 $cfg->{"abc"}`;
    ....
}

my $cfg = cfgRead();
subOne($cfg);

#3


6  

It's simply a helpful comment, because it's pretty unusual to store data in something but never look in it again. Lets look at a more helpful example instead:

它只是一个有用的注释,因为在某些东西中存储数据是很不寻常的,但是从不会再看到它。让我们来看一个更有用的例子:

use warnings;
$something = 1;
$something = $something + 1;

That, of course, works great as you'd expect. But consider a mistake:

当然,这一切都如你所愿。但考虑一个错误:

use warnings;
$something = 1;
$something = $somehting + 1;

If you didn't look closely you wouldn't notice the spelling mistake and probably wouldn't figure out why the final value was wrong (since $somehting would be effectively 0).

如果你不仔细看,你就不会注意到拼写错误,可能也不会明白为什么最终的值是错的(因为$somehting实际上是0)。

In this case the warning:

在这种情况下,警告:

Name "main::somehting" used only once: possible typo at tmp.pl line 3.

Is much more useful. It shows you a possible typo.

是更有用的。它显示了一个可能的输入错误。

(use strict; would be even better in here, of course)

(使用严格;当然,在这里会更好

#1


9  

There are a few odd things here.

这里有一些奇怪的东西。

First: when you have use strict active, you will get a warning if you use a variable without declaring it, or referencing it by fully qualified name.

首先:当您使用严格的活动时,您将得到一个警告,如果您使用一个变量而不声明它,或者以完全限定的名称引用它。

What you have actually done is to declare a local %cfg with my() in xyzzy.pl, and then to reference a different, package-global variable %main::cfg (implicitly declared by using its fully qualified name).

实际上,您所做的是在xyzzy中使用my()来声明一个本地%cfg。然后引用一个不同的包全局变量%main::cfg(通过使用它的完全限定名来隐式声明)。

To make the reference link to the same %cfg that you declared, you should declare it our() to make it package-global. Then you can either reference it as $main::cfg{} in both places (or just $cfg{} from xyzzy.pl), or else you can declare it our() in plugh.pm as well (so that you can use the bare %cfg in both places).

为了使引用链接到您声明的相同的%cfg,您应该声明我们()使其成为包全局的。然后,您可以将其作为$main::cfg{}在两个位置(或仅从xyzzy.pl中获得$cfg{}),或者您可以在plugh中声明我们的()。pm也可以(这样你可以在两个地方使用光%cfg)。

The odd thing is that you do have two references to that variable, so you shouldn't get the warning. I think what has happened here is that the implicit declarations in two separate files are assumed to be separate variables.

奇怪的是,你确实有两个对那个变量的引用,所以你不应该得到警告。我认为这里发生的情况是,两个独立文件中的隐式声明被假定为单独的变量。

xyzzy.pl:

xyzzy.pl:

require plugh;

our (%cfg);

sub subOne () {
   my $list = `ls -1 $cfg{"abc"}`;
   ...
}

plugh.pm:

plugh.pm:

our(%cfg);
sub cfgRead () { $cfg{"abc"} = "/usr"; }

#2


12  

I think your original question is answered, so I'll just pass along my advice. Don't ever use globals if you can avoid it. You are using subroutines as mere clusters of code and not passing them any arguments, and that's where your problems come from.

我认为你最初的问题得到了回答,所以我就把我的建议转达给你。如果可以避免使用全局变量,请不要使用全局变量。您使用子例程仅仅是代码的集群,并没有传递任何参数,这就是您的问题的来源。

Module:

模块:

sub cfgRead {
    my %cfg;
    $cfg{"abc"} = "/usr";
    ...
    return \%cfg;
}

Main:

主要:

sub subOne {
    my $cfg = shift;
    my $list = `ls -1 $cfg->{"abc"}`;
    ....
}

my $cfg = cfgRead();
subOne($cfg);

#3


6  

It's simply a helpful comment, because it's pretty unusual to store data in something but never look in it again. Lets look at a more helpful example instead:

它只是一个有用的注释,因为在某些东西中存储数据是很不寻常的,但是从不会再看到它。让我们来看一个更有用的例子:

use warnings;
$something = 1;
$something = $something + 1;

That, of course, works great as you'd expect. But consider a mistake:

当然,这一切都如你所愿。但考虑一个错误:

use warnings;
$something = 1;
$something = $somehting + 1;

If you didn't look closely you wouldn't notice the spelling mistake and probably wouldn't figure out why the final value was wrong (since $somehting would be effectively 0).

如果你不仔细看,你就不会注意到拼写错误,可能也不会明白为什么最终的值是错的(因为$somehting实际上是0)。

In this case the warning:

在这种情况下,警告:

Name "main::somehting" used only once: possible typo at tmp.pl line 3.

Is much more useful. It shows you a possible typo.

是更有用的。它显示了一个可能的输入错误。

(use strict; would be even better in here, of course)

(使用严格;当然,在这里会更好