How to use a module in Perl - perl

Guys im really confused on how to use a module i just installed in Perl.
I installed a Corelist module in Perl. And i want to display all the modules that came with Perl 5.006. But there is a hint in doing this by using this code which i dont understand:
my %modules = %{ $Module::CoreList::version{5.006} };
But when i did this
#! usr/bin/perl
use warnings;
use strict;
my %modules = %{$Module::CoreList::version{5.006}};
print %modules;
it gives this error: Module::CoreList::version used only once . I also tried putting
use Module::CoreList; still no luck

The name of the module is 'Module::CoreList'. You should put the following line into your programme:
use Module::CoreList;
Also note the capital L. Perl is case sensitive.

If you simply want to print the hash, just add Data::Dumper module along with strict and warnings, then
print Dumper(\%modules);
Updated: try something like
use warnings;
use strict;
use Module::CoreList;
use Data::Dumper;
my %module = %{ $Module::CoreList::version{5.006} };
print Dumper (\%module);

Related

Program unexpectedly reports "Use of uninitialized value"

This is with regard to my previous question
Hold Subroutine response and set to variable in Perl
The statement Module::thesub("hello")
worked in Module.pm but fails if I move it to main.pl
main.pl
#!/usr/bin/perl
use strict;
use warnings;
use Module;
Module::thesub("hello");
Module.pm
#!/usr/bin/perl
use strict;
use warnings;
package Module;
sub thesub {
state $stored;
$stored = shift if #_;
return $stored;
}
my $testvar = thesub();
print $testvar;
1;
I get this error
Use of uninitialized value $testvar
which means the variable $testvar has no value.
How can I fix this?
Statements in a module run when the module is loaded, at use Module;. At that time thesub() still wasn't called with an argument and $stored in it is undefined. So that is what $testvar gets when it's assigned and the warning is emitted when it's printed.
The $testvar can be used in main
use strict;
use warnings;
use Module;
Module::thesub("hello");
my $testvar = Module::thesub();
even though I am not sure from the question what the purpose of this is.
Remove the assignment and print of $testvar from the module. Note that you'll also need use feature 'state'; at the beginning of the module, to enable the feature pragma.
A few comments on the module you show
No need for #!/usr/bin/perl, as a module is generally not meant to be run
The package Module; is commonly the first line
While what you have works, consider making symbols from the module available to the calling code, so that it can import them and simply say thesub(). A common way is
package Module;
use warnings;
use strict;
use Exporter qw(import);
our #EXPORT_OK = qw(thesub);
sub thesub { ... }
1;
and in the main
use Module qw(thesub);
thesub("hello");
See Exporter for starters and search SO, where there are great many posts on this.

Importing variable into Perl package

I'm writing a basic program whose core logic is split across several project-specific modules for cleanliness (keeping subroutines organised by their purpose in the program's logic).
Suddenly had trouble exposing an option from the main package in one of the modules, and using the our statement appeared to have no effect.
For brevity, I'll copy+paste an isolated test case I wrote to examine this behaviour:
main.pl
#!/usr/bin/perl
use warnings;
use strict;
use File::Basename;
# The variable to be read by the module.
our $verbose = 1;
# Load Output.pm from directory
use lib dirname "$0";
use Output;
write_message "Hello, world\n";
Output.pm
package Output;
use warnings;
use strict;
use parent "Exporter";
our #EXPORT = qw(write_message);
# Should be imported?
our $verbose;
sub write_message {
print $_[0] unless !$verbose;
}
1;
Expected result: "Hello, world"
Actual result: Dead silence
It's quite possible that what I'm trying to achieve isn't even possible in Perl, as this isn't the intended use of modules (and heck, I understand why that'd be the case).
I'm still quite new to Perl and there are some things I'm struggling to wrap my head around. I've seen people recommend using the our declarator to expose a variable across packages, but I can't understand why this isn't working.
PS: If anybody knows a better approach to splitting an app's program-specific logic between modules, I'd appreciate some pointers too. :) But first and foremost, I'd prefer to learn why our-ing a variable isn't working.
An our statement just creates a package variable (whereas my creates a lexical variable). It has nothing to do with exporting
The best option is probably to declare the variable in the Output package and access it as $Output::verbose elsewhere. Like this
main.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use lib dirname $0;
use Output;
$Output::verbose = 1;
write_message "Hello, world\n";
Output.pm
package Output;
use strict;
use warnings;
use Exporter 5.57 'import';
our #EXPORT = qw/ write_message /;
our $verbose;
sub write_message {
print $_[0] if $verbose;
}
1;
Note that I have also removed the incorrect quotes from around $0, and ever since version 5.57 of Exporter it has been possible (and preferable) to import it's import subroutine instead of subclassing it
our declares a package variable in the current package. The one in main.pl refers to $main::verbose; the one in Output.pm refers to $Output::verbose.
You can use the full name $main::verbose to access the variable from anywhere, but you can't really "export" it because exporting refers to making symbols accessible to users of your module. You're trying to do the opposite.

Input parameter for perl CGI script

I need some insight on my Perl CGI script.
First of all all this is running under webmin so i'm doing a custom module.
I'm calling a CGI Perl script passing 2 parameter from another Perl CGI. The link I'm calling is in the following format:
http://IP:8080/foobar/alat.cgi?sysinfo=xxxxxxx&SR=yyyyyyyy
The alat.cgi script look like this
#!/usr/bin/perl
use CGI qw(:standard);
ReadParse();
$q = new CGI;
my $dir = $in->param('SR');
my $s = $in->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s"<br>";
The only output I get printed is the value of $dir and $s seems to be empty.
What am I doing wrong?
As #Сухой27 said, add use strict;, but also use warnings; to the top of your script, right below the shebang (#!/usr/bin/perl) line. Those will tell you about syntax errors and other stuff where Perl is doing something other than you might intend.
With CGI (which is btw not part of the Perl core in the latest 5.22 release any more) and the object oriented approach you are tyring to take, you don't need to use ReadParse(). That is an abomination left in from Perl 4's cgilib.pl times.
I don't know what your ui_print_header function does. I'm guessing it outputs a bunch of HTML. Are you sure you defined it?
With fixing all your syntax errors and using modern syntax, your program would look like this. I'll break down what is happening for you.
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
# you need to declare this to use it below
my %text = ( edit_title => 'foo' );
# we declare this sub further down
ui_print_header(undef, $text{'edit_title'} . $dir, q{});
print $dir . '<br />';
print $s . '<br />';
sub ui_print_header {
my ( $foo, $title, $dir, $bar ) = #_;
# do stuff here...
}
Let's look at some of the things I did here.
Saying new CGI as the CGI docs suggest is fine, but since we are using the OOP way you can use the more common CGI->new. It's the same thing really, but it's consistent with the rest of the OOP Perl world and it's more clear that you are calling the new method on the CGI package.
If you have $q, keep using it. There is no $in.
Declare all your variables with my.
Declare %text so you can use $text{'edit_title'} later. Probably you imported that, or ommitted it from the code you showed us.
Declare ui_print_header(). See above.
q{} is the same as '', but it's clearer that it's an empty string.
thank you everyone for the very quick answer, and as I was suspecting I just had some silly mistake.
Adding here the corrected code that now works
#!/usr/bin/perl
# Run alat on selected sysinfo and allow display of output
#use strict;
use diagnostics;
require 'recoverpoint-lib.pl';
use CGI qw(:standard);
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";
Just to clarify for some of previous answer, this is a custom module of webmin so variable $text is imported and function ui_print_header is a webmin defined one, it basically print the page header in HTML
As you enable strict and warnings you can easily know the errors.Also you should check Apache error logs, I think the script should be like this:
#!/usr/bin/perl
use CGI qw(:standard);
use strict;
use warnings;
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";

what does perl use Cwd qw(); mean?

What does
use Cwd qw();
mean in perl?
I know qw gives quotes to each elements inside ()
But what about this case?
The qw() is a fancy way of writing an empty list. Doing () would be two characters shorter.
Passing an empty list to use is important to avoid importing. From the use documentation:
If you do not want to call the package's import method (for instance, to stop your namespace from being altered), explicitly supply the empty list
E.g. by default, the Cwd module exports getcwd. This doesn't happen if we give it the empty list:
use strict;
use Cwd;
print "I am here: ", getcwd, "\n";
works, but
use strict;
use Cwd ();
print "I am here: ", getcwd, "\n";
aborts compilation with Bareword "getcwd" not allowed while "strict subs" in use.
I believe that since qw() after use Module is for importing subroutines, when left empty it simply loads the module but doesn't import any subroutines into the namespace.
For example this throws an error since getcwd is not imported:
#!/usr/bin/perl
use warnings;
use strict;
use Cwd qw();
my $dir=getcwd;
But I'm not sure if this is the answer you was looking for..!
Usually it "imports" commands so you don't have to create an object and call the function on them.
Example (from perlmonks):
#without qw
use CGI;
my $q = CGI->new();
my $x = $q->param('x');
#with qw
use CGI qw/:standard/;
my $x = param("x")
Source: http://www.perlmonks.org/?node_id=1701
Most modules have import groups like :all or :standard also.

How to share/export a global variable between two different perl scripts?

How do we share or export a global variable between two different perl scripts.
Here is the situation:
first.pl
#!/usr/bin/perl
use strict;
our (#a, #b);
.........
second.pl
#!/usr/bin/perl
use strict;
require first.pl;
I want to use global variable (#a, #b) declared in first.pl
Also,suppose there's a variable in second perl file same as first perl file. But I want to use first file's variable. How to achieve this?
In general, when you are working with multiple files, and importing variables or subroutines between them, you will find that requiring files ends up getting a bit complicated as your project grows. This is due to everything sharing a common namespace, but with some variables declared in some files but not others.
The usual way this is resolved in Perl is to create modules, and then import from those modules. In this case:
#!/usr/bin/perl
package My::Module; # saved as My/Module.pm
use strict;
use warnings;
use Exporter;
our #ISA = 'Exporter';
our #EXPORT = qw(#a #b);
our (#a, #b);
#a = 1..3;
#b = "a".."c";
and then to use the module:
#!/usr/bin/perl
use strict;
use warnings;
use My::Module; # imports / declares the two variables
print #a;
print #b;
That use line actually means:
BEGIN {
require "My/Module.pm";
My::Module->import();
}
The import method comes from Exporter. When it is called, it will export the variables in the #EXPORT array into the calling code.
Looking at the documentation for Exporter and perlmod should give you a starting point.
They will share global variables, yes. Are you seeing some problem with that?
Example:
first.pl:
#!/usr/bin/perl
use strict;
use warnings;
our (#a, #b);
#a = 1..3;
#b = "a".."c";
second.pl:
#!/usr/bin/perl
use strict;
use warnings;
require "first.pl";
our (#a,#b);
print #a;
print #b;
Giving:
$ perl second.pl
123abc
Cant you use package and export the variable?