Perl: как сделать переменные из обязательного скрипта доступными в нужном скрипте - PullRequest
3 голосов
/ 25 сентября 2011

пример

out.pl:

(my|our|local|global|whatever???) var = "test";
require("inside.pm");

inside.pm:

print $var;

Я не хочу использовать пакеты - это подавляет мои потребности :) Спасибо!

Ответы [ 2 ]

5 голосов
/ 25 сентября 2011

Вы всегда используете пакет, даже если вы не используете объявление package.По умолчанию вы работаете в пакете main.

Все переменные, которые вы объявляете с помощью our, являются переменными пакета и должны быть доступны во всем пакете.Вот пример:

#! /usr/bin/env perl
# test2.pl

use strict;
use warnings;

our $foo = "bar";
1;

Поскольку $foo объявлена ​​как переменная пакета, она будет доступна в других программах:

#! /usr/bin/env perl
use strict;
use warnings;

require "test2.pl";

our $foo;
print "The value of \$foo is $foo\n";

Теперь я дал вам достаточно веревки,Я скажу вам не вешаться с этим.

Это ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО ПЛОХАЯ ИДЕЯ .Обратите внимание, что $foo получает значение от какого-то таинственного механизма, который почти невозможно выяснить?

Пакеты слишком сложны ?В самом деле?Это не так сложно!Посмотрите на этот пример:

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

our $foo = "bar";
1;

Не сильно отличается от предыдущего, за исключением того, что я добавил объявление package и теперь вызываю мою программу test2.pm вместо test2.pl.

Вот как ядоступ к нему:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

print "The value of \$foo from package test2 is $test2::foo\n";

Все, что мне нужно было сделать, это использовать имя пакета в переменной.Это ПЛОХАЯ ИДЕЯ , но она лучше, чем ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО ПЛОХАЯ ИДЕЯ , показанная выше.

По крайней мере, вы знаете, откуда взялась ценность.Это пришло от test2.pm.И вы можете получить доступ к переменной, если установите ее в подпрограмме.

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

Обратите внимание, что в подпрограмме fooloader установлено $foo.И вот моя другая программа для доступа к ней:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

Теперь вы можете использовать Exporter для экспорта ваших подпрограмм (и даже переменных), но вы больше не видите этого слишком много.В основном потому, что это ДЕЙСТВИТЕЛЬНО ПЛОХАЯ ИДЕЯ .Не так плохо, как оригинал ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО ПЛОХАЯ ИДЕЯ , но хуже, чем ПЛОХАЯ ИДЕЯ выше:

#! /usr/bin/env perl
# test2.pm

package test2;
use base qw(Exporter);

our @EXPORT = qw(fooloader);
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

Теперь я могу использовать подпрограмму fooloader без имени пакета:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

Проблема, конечно, в том, что у вас нет реального представления о том, откуда берется подпрограмма fooloader.Если бы вы использовали @EXPORT_OK вместо @EXPORT, вы могли бы использовать use test2 qw(fooloader); и документ, из которого поступала функция fooloader.Это также поможет вам не создавать собственную функцию fooloader в собственной программе и не переопределять ту, которую вы импортировали.Тогда удивляйтесь, почему ваша программа больше не работает.

Кстати, вы также можете экспортировать переменные, а не только функции.Однако это становится ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО ПЛОХОЙ - НЕТ УЖАСНОЙ ИДЕИ , потому что это нарушает все причины, по которым вы используете пакеты в первую очередь.Если вы собираетесь это сделать, зачем беспокоиться о пакетах?Почему бы просто не взять пистолет и не выстрелить себе в ногу?

Лучший и предпочтительный способ - использовать объектно-ориентированный Perl и делать это в ТОЧНО ПРАВИЛЬНЫМ СПОСОБОМ ,Способ, где вы точно знаете, что происходит и почему.И позволяет легко понять, что делает ваш код.Способ, который сводит ошибки к минимуму.

Вот полностью объектно-ориентированный класс Test2:

#! /usr/bin/env perl
# Test2.pm

package Test2;

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    return $self;
}

sub FooValue {
    return "bar";
}
1;

И используя этот Test2 класс:

#! /usr/bin/env perl
use strict;
use warnings;

use Test2;

my $tester = Test2->new;

print "The value of foo from package test2 is " . $tester->FooValue . "\n";

Это лучший способ сделать это потому, что даже если вы используете пакеты, вы можете манипулировать значением $test2::foo, и оно будет изменено во всей вашей программе.Представьте, что если бы это было, скажем, $constants::pi и где-то вы изменили его с 3.14159 на 3. С тех пор использование $constants::pi даст вам неправильное значение.Если вы используете объектно-ориентированный метод, вы не сможете изменить значение метода Constant-> Pi.Это всегда будет 3.14159.

Итак, что мы узнали сегодня?

Мы узнали, что в Perl очень легко сделать что-то, что ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО ПЛОХОIDEA , но для использования пакетов не требуется много работы, поэтому он просто становится BAD IDEA .И, если вы начнете изучать немного объектно-ориентированного Perl, вы на самом деле, без особых усилий, сможете сделать все это в ТОЧНО ПРАВИЛЬНЫМ ПУТИ .

Выбор за вами. Просто помните, что нога, которую вы снимаете, вероятно, будет вашей собственной.

4 голосов
/ 25 сентября 2011

Это будет работать с our.

$ cat out.pl
our $var = "test";
require("inside.pm");

$ cat inside.pm 
print "Testing...\n";
print "$var\n";

$ perl out.pl
Testing...
test

Это работает, потому что our делает $var глобальным, а inside.pm выполняется в области действия с определением $var.Не уверен, что это рекомендуемая техника, но, тем не менее, это интересный вопрос!

РЕДАКТИРОВАТЬ : Необходимо уточнить (исправление) ответ на основе комментария:

С документация по функции Perl our:

our связывает простое имя с переменной пакета (читай: глобальная) в текущем пакете для использования в текущей лексической области.Другими словами, our имеет те же правила области видимости, что и my или state, но не обязательно создает переменную.

Таким образом, используя our, мы получаем $var стекущий пакет (здесь, вероятно, main), и мы можем использовать его в своей области видимости.По сути, он становится «глобальным» для кода в нужном вам файле.

A true global вводится без our, поскольку переменные по умолчанию имеют значение global.Но я не знаю никого, кто бы порекомендовал их.

...