Calling a sub in main script from module

F

fatted

Having called a function from a module, I'd like that module function
to call a function from the main script, but I can't figure out how
(had a look through perlsub, perlmod,...)
Simple Example:

####### script.pl

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

my $file = 'not_there.txt';

file_readable($file);

sub write_log
{
my $msg = shift;
print $msg."\n";
}

###### Readable.pm

package Readable;
use Exporter;
@ISA = ('Exporter');
@EXPORT = qw(&file_readable);

sub file_readable
{
my $file = shift;
open(IN,"<",$file) or $main::write_log("No thanks");
}

1;

######

When I run script.pl, I get:
syntax error at Readable.pm line 9, near "$main::write_log("
Compilation failed in require at ./script.pl line 5.
BEGIN failed--compilation aborted at ./script.pl line 5.

Whats the correct way to do this?

While we're here, if, use strict; use warnings; are used in a script
does this apply to any modules which are included by the script (via
use)?
 
M

Matthias Weckman

fatted said:
Having called a function from a module, I'd like that module function
to call a function from the main script, but I can't figure out how
(had a look through perlsub, perlmod,...)

You call fully qualified subs like this:

package::subroutine(@arguments);
Simple Example:

[snip]

###### Readable.pm

package Readable;
use Exporter;
@ISA = ('Exporter');
@EXPORT = qw(&file_readable);

sub file_readable
{
my $file = shift;
open(IN,"<",$file) or $main::write_log("No thanks");
}

1;

######

When I run script.pl, I get:
syntax error at Readable.pm line 9, near "$main::write_log("
Compilation failed in require at ./script.pl line 5.
BEGIN failed--compilation aborted at ./script.pl line 5.

That's right. $main::write_log would be a variable, so $v(...) is
syntactically incorrect.
Remove the $ sign from that call.
Whats the correct way to do this?

main::write_log(...).

While you're asking... A correct way of testing if a file is readable is
using the -r or -R file test. (See the first entry in the Alphabetical
section of perlfunc).
You don't have to open the file to see if you can read from it:

sub file_readable
{
my $file = shift;
-f $file and -r $file or main::write_log("No thanks");
}

While we're here, if, use strict; use warnings; are used in a script
does this apply to any modules which are included by the script (via
use)?

No, use strict; and use warnings; are lexically scoped. This means they
are valid only in the current file (or block, so you can turn them off
in specific places if you have to). The nice thing about that is that
you can specify the level of strictness or warnings within each module.

See perlmodlib, first section, for more details

Matthias
 
A

Anno Siegel

fatted said:
Having called a function from a module, I'd like that module function
to call a function from the main script, but I can't figure out how

You can do that -- your error below is trivial -- but the big question
is *why* would you want to do that.

The purpose of building a module (instead of putting everything in the
main program) is to make a set of functions independent of the main
program. When the module calls a function from the main program, that
independence is lost, so you might as well keep everything in one file.
(had a look through perlsub, perlmod,...)
Simple Example:

####### script.pl

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

my $file = 'not_there.txt';

file_readable($file);

sub write_log
{
my $msg = shift;
print $msg."\n";
}

###### Readable.pm

package Readable;
use Exporter;
@ISA = ('Exporter');
@EXPORT = qw(&file_readable);

sub file_readable
{
my $file = shift;
open(IN,"<",$file) or $main::write_log("No thanks");
^
What is the "$" doing there? That's no way to call a program.
(Then again, you may have been clairvoyant. See below.)

open(IN,"<",$file) or main::write_log("No thanks");
}

1;

######

When I run script.pl, I get:
syntax error at Readable.pm line 9, near "$main::write_log("
Compilation failed in require at ./script.pl line 5.
BEGIN failed--compilation aborted at ./script.pl line 5.

Whats the correct way to do this?

There is no one correct way, but a better way to call back into the
main program is for the module to have a method (not necessarily in
the OO sense) for the main program to *tell* the module which subroutine
to call. Change Readable.pm like this:

package Readable;
use Exporter;
@ISA = ('Exporter');
@EXPORT = qw(&file_readable &set_logger);

my $logger;

sub set_logger {
$logger = shift;
}

sub file_readable
{
my $file = shift;
open(IN,"<",$file) or $logger->("No thanks");
}

1;

(You even get the dollar on the sub call back :)

Now the main program becomes:

#!/usr/bin/perl
use strict; use warnings; $| = 1; # @^~`

use Readable;

set_logger( sub {
my $msg = shift;
print $msg."\n";
}
);

my $file = 'not_there.txt';

file_readable($file);

The point of the changes is that now Readable.pm no longer has to know
how the logging routine is named in the main program, so it can again
work with a variety of main programs. Consequently, the logging routine
doesn't even have a name anymore, though you could use a named one
as well.
While we're here, if, use strict; use warnings; are used in a script
does this apply to any modules which are included by the script (via
use)?

No, they don't propagate. A file is a lexical unit (block) of itself,
and the effects of "use strict" and "use warnings" are confined to
the current lexical scope.

Anno
 
B

Ben Morrow

Matthias Weckman said:
While you're asking... A correct way of testing if a file is readable is
using the -r or -R file test. (See the first entry in the Alphabetical
section of perlfunc).
You don't have to open the file to see if you can read from it:

However, it is more better to. If you test with -r then there is a
race condition between when you make the test and when you
subsequently open the file: the permissions could have changed.

Ben
 
F

fatted

Matthias Weckman said:
fatted wrote:


main::write_log(...).

I have no idea where that dollar came from. I was beating my head for
hours over that. I am now attempting to engage my brain :)
While you're asking... A correct way of testing if a file is readable is
using the -r or -R file test.

I was just giving a simple example to show the problem, not ideal code
(or even close :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top