Почему Perl говорит, что я использую это только один раз? Почему это вообще проблема? - PullRequest
4 голосов
/ 02 февраля 2012

У меня есть код, который мне удалось сузить до следующего примера наименьшего кода.

Сначала у меня есть модуль plugh.pm, который отвечает за чтение в файле конфигурации. В основном это можно заменить следующим текстом, который устанавливает один элемент конфигурации:

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

Затем у меня есть основная программа, которая использует этот модуль следующим образом, просто вызывает функцию для настройки элементов конфигурации и затем использует один из этих элементов в подпрограмме:

#!/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();

Теперь, когда я запускаю это, я получаю следующий вывод: первая строка - стандартная ошибка, а остальные - стандартный вывод:

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

Строка, на которую он жалуется, - это создание подпроцесса ls -1. У меня вопрос просто: и что? Да, я использую его только один раз, но почему это вообще проблема?

Если бы я никогда не использовал его, тогда хорошо, но я не понимаю, почему Perl предупреждает меня об использовании его только один раз.

Я получаю переменную из ассоциативного массива, а затем использую ее для получения списка каталогов. Существует ли какое-то странное руководство по Perl, согласно которому переменные состояний должны использоваться как минимум дважды? Семь раз? Сорок два? Я серьезно озадачен.

Ответы [ 3 ]

12 голосов
/ 02 февраля 2012

Я думаю, что на ваш оригинальный вопрос ответили, поэтому я просто передам свой совет.Никогда не используйте глобалы, если вы можете избежать этого.Вы используете подпрограммы как простые кластеры кода и не передаете им никаких аргументов, и вот откуда возникают ваши проблемы.

Модуль:

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

Основной:

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

my $cfg = cfgRead();
subOne($cfg);
9 голосов
/ 02 февраля 2012

Здесь есть несколько странных вещей.

Во-первых: если у вас активен use strict, вы получите предупреждение, если вы используете переменную без ее объявления, или , ссылаясь на нее по полному имени.

Что вы на самом деле сделали, так это объявили локальную %cfg с my() в xyzzy.pl, а затем сослались на другую глобальную переменную пакета %main::cfg (неявно объявленную с помощью его полное имя).

Чтобы сделать ссылку на тот же %cfg, который вы объявили, вы должны объявить его our(), чтобы сделать его глобальным для пакета. Затем вы можете ссылаться на него как $main::cfg{} в обоих местах (или просто $cfg{} из xyzzy.pl), или вы также можете объявить его our() в plugh.pm (так что вы можете использовать только% cfg) в обоих местах).

Странно то, что у вас есть две ссылки на эту переменную, поэтому вы не должны получать предупреждение. Я думаю, что здесь произошло то, что неявные объявления в двух отдельных файлах считаются отдельными переменными.

xyzzy.pl:

require plugh;

our (%cfg);

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

plugh.pm:

our(%cfg);
sub cfgRead () { $cfg{"abc"} = "/usr"; }
6 голосов
/ 02 февраля 2012

Это просто полезный комментарий, потому что довольно необычно хранить данные в чем-либо, но никогда не просматривать их снова. Давайте рассмотрим более полезный пример:

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

Это, конечно, прекрасно работает, как и следовало ожидать. Но учтите ошибку:

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

Если вы не присмотритесь, вы не заметите орфографическую ошибку и, возможно, не поймете, почему окончательное значение было неправильным (поскольку $somehting будет равно 0).

В этом случае предупреждение:

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

Гораздо полезнее. Это показывает вам возможную опечатку.

(use strict; здесь было бы еще лучше, конечно)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...