volatile
говорит компилятору, что Ваша переменная может быть заменена другими средствами, чем код, который получает доступ к нему. например, это может быть ячейка памяти I/O-mapped. Если это не определяется в таких случаях, некоторые переменные доступы могут быть оптимизированы, например, ее содержание может быть сохранено в регистре и ячейке памяти не, чтение въезжает задним ходом снова.
If the file is invoked as a script, there will be no caller so you can use:
main() unless caller;
See brian d foy's explanation.
#!/usr/bin/perl
use strict;
use warnings;
main() unless caller;
sub main {
my $obj = MyClass->new;
$obj->hello;
}
package MyClass;
use strict;
use warnings;
sub new { bless {} => shift };
sub hello { print "Hello World\n" }
no warnings 'void';
"MyClass"
Output:
C:\Temp> perl MyClass.pm
Hello World
Using from another script:
C:\Temp\> cat mytest.pl
#!/usr/bin/perl
use strict;
use warnings;
use MyClass;
my $obj = MyClass->new;
$obj->hello;
Output:
C:\Temp> mytest.pl
Hello World
Я называю это «модулями» первоначально в моей статье Скрипты как модули для The Perl Journal (теперь Dr. Dobbs ). Погуглите этот термин, и вы получите нужные ресурсы. Синан уже связался с моими источниками разработки для одной из моих книг, где я говорю об этом. Вам также может понравиться Как сценарий становится модулем .
Лучше не делать этого и вместо этого использовать структурированный подход, например MooseX :: Runnable .
Ваш класс будет выглядеть так:
class Get::Me::Data with (MooseX::Runnable, MooseX::Getopt) {
has 'dsn' => (
is => 'ro',
isa => 'Str',
documentation => 'Database to connect to',
);
has 'database' => (
is => 'ro',
traits => ['NoGetopt'],
lazy_build => 1,
);
method _build_database {
Database->connect($self->dsn);
}
method get_data(Str $for_person){
return $database->search({ person => $for_person });
}
method run(Str $for_person?) {
if(!$defined $for_person){
print "Type the person you are looking for: ";
$for_person = <>;
chomp $for_person;
}
my @data = $self->get_data($for_person);
if(!@data){
say "No data found for $for_person";
return 1;
}
for my $data (@data){
say $data->format;
}
return 0;
}
}
Теперь у вас есть класс, который можно легко использовать внутри вашей программы:
my $finder = Get::Me::Data->new( database => $dbh );
$finder->get_data('jrockway');
Внутри интерактивного сценария, который больше, чем просто метод "run", указанный выше:
...
my $finder = Get::Me::Data->new( dsn => 'person_database' );
$finder->run('jrockway') and die 'Failure'; # and because "0" is success
say "All done with Get::Me::Data.";
...
Если вы просто хотите сделать это автономно, вы можете сказать:
$ mx-run Get::Me::Data --help
Usage: mx-run ... [arguments]
--dsn Database to connect to
$ mx-run Get::Me::Data --dsn person_database
Type the person you are looking for: jrockway
<data>
$ mx-run Get::Me::Data --dsn person_database jrockway
<data>
Обратите внимание, как небольшой код, который вы написали, и насколько гибким будет полученный класс. "main if! caller" - это хорошо, но зачем беспокоиться, когда можно сделать лучше?
(Кстати, у MX :: Runnable есть плагины; так что вы можете легко увеличить объем выводимых отладочных данных, перезапустите приложение, когда код изменений, сделать приложение постоянным, запустить его в профилировщике и т. д.)