Softpanorama

Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
May the source be with you, but remember the KISS principle ;-)
Skepticism and critical thinking is not panacea, but can help to understand the world better

Perl Tips/Snippets

News Recommended Links Perl Style Perl Programming Environment Perl as a command line utility tool Perl Debugging
Perl Xref Perl One Liners Perl Options Perl options processing Pipes in Perl Perl POD documentation

Using VIM with Perl

AWK one liners Shell Tips and Tricks VIM Tips Humor Etc

One problem with Perl it is impossible to remember all the language, it is just too big. For example, the details for printf, exotic futures of regular expression engine and command line switches.  You need some help from sheet sheets. There are many on the Web and you can create your own combining best features of each into one the is more suitable for your needs. Among possible sources:

Here are some of the most useful Perl tips and snippets that I collected:

  1. If you use OFMs it is easy to save stokes in checking Perl scripts. Configure extension pl  or usemenu item p  to invoke perl -cw !.! (!.! is FAR idiom, other OFMs like Midnight Commander use different macros).

     

  2. Special variable $^O contains the name of your operating system in the format provided by uname.

    No need for something like:

    $OS=`uname`; chomp $OS;

    Some additional scalars that Perl defines for you:

  3. Create a log file and write important messages to the log file
     

  4. In more or less complex script control printing of debugging information using some variable (for example $debug ). Design and maintain your own system of diagnostic output from various subroutines of the program

    For more or less complex program diagnostic output using special print statements is the most efficient debugging method. It should be controlled by special variable, for example $debug, which can be integer or bit value. For example:

    ($debug) && print "text=$test";
    You can also use binary numbers and & operator which permits you operating with small sets of debug flags one for each section of a program The following code snippet demonstrates this:
    # A $debug eight bits (one byte)
    $debug=0b10110000;
    
    if ( $debug & 0b10000000) {
       print "Some dignistic output\n";
    } elsif ( $debug & 0b0100000) {
       print "Other (possiblly more detailed diagnistic output)
    }
  5. Initializing list of words use qw
    @mylist=qw(one, two, three, four);
  6. You can check Perl syntax in VIM on each save
    au BufWritePost *.pl,*.pm !perl -c %

    Every time you save a .pl or .pm file, it executes perl -c and shows you the output.

    ~~
    naChoZ

  7. Dynamic activation of the debugger (from "Perl debugged" book):
    while (<INPUT>) {
       $DB::trace = 1, next if /debug/;
       $DB::trace = 0, next if /nodebug/;
       # more code
    }

    When run under the debugger, this enables tracing when the loop encounters an input line containing "debug" and ceases tracing upon reading one containing "nodebug".

    You can switch to interactive debugging  by using:

    $DB::single = 1

    instead. That also provide a way you can debug code in BEGIN blocks (which otherwise are executed before control is given to the debugger).

  8. Sometimes it makes sense to use regular expressions instead of substr. One such task is extraction of component of date, for example:
    $cur_date='20060325';
    (year, $month, $day)=$cur_date=~/(\d{4})(\d\d)(\d\d)/;
  9. Getting Perl cross-reference reports. The B::Xref module can be used to generate cross-reference reports for
    Perl programs.
    perl -MO=Xref[,OPTIONS] scriptname.plx
  10. Setting a value of parameter to default value:
    # --- process the second parameter
    $msglevel=($ARGV[1]) ? $ARGV[1] : $msglevel; # defaults is the three digit constant(see below)
    ($msglevel1, $msglevel2, $testing) = split(//,$msglevel); # get one byte flags
  11. Creating timestamp
    # Timestamp
    #
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
    $year+=1900;
    $mon++;
    for ($mon, $mday, $hour, $min, $sec) {
       if (length($_)==1) {
           $_="0$_";
       }
    } 
  12. Move via link/unlink (should be the same filesystem):
    link($_[0], $target);
    if (-e $target) {
       unlink($_[0]);
    } else {
       logger("SFail to move the file '$_[0]' to '$home/$_[1]/$target' \n");
       return;
    }
  13. Removing duplicates: here the second part will be executed only if $new{$match} is still undefined:
    if ( $new{$match}++ || !( $tags{$match} = sprintf( "%s\t%s\t?^%s\$?\n", $match, $ARGV, $_ ) ) )

Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Feb 27, 2020] A `printf` format reference page (cheat sheet) by alvin alexander

Feb 27, 2020 | alvinalexander.com

By Alvin Alexander. Last updated: November 21 2019 Table of Contents

  1. printf formatting with Perl and Java
  2. A summary of printf format specifiers
  3. Controlling integer width with printf
  4. Left-justifying printf integer output
  5. The printf integer zero-fill option
  6. printf integer formatting
  7. formatting floating point numbers with printf
  8. printf string formatting
  9. printf special characters
  10. Related printf content

Summary: This page is a printf formatting cheat sheet. I originally created this cheat sheet for my own purposes, and then thought I would share it here.

A great thing about the printf formatting syntax is that the format specifiers you can use are very similar -- if not identical -- between different languages, including C, C++, Java, Perl, PHP, Ruby, Scala, and others. This means that your printf knowledge is reusable, which is a good thing.

Back to top printf formatting with Perl and Java

In this cheat sheet I'll show all the examples using Perl, but at first it might help to see one example using both Perl and Java. Therefore, here's a simple Perl printf example to get things started:

printf("the %s jumped over the %s, %d times", "cow", "moon", 2);

And here are three different Java printf examples, using different string formatting methods that are available to you in the Java programming language:

System.out.format("the %s jumped over the %s, %d times", "cow", "moon", 2);
System.err.format("the %s jumped over the %s, %d times", "cow", "moon", 2);
String result = String.format("the %s jumped over the %s, %d times", "cow", "moon", 2);

As you can see in that last String.format example, that line of code doesn't print any output, while the first line prints to standard output, and the second line prints to standard error.

In the remainder of this document I'll use Perl examples, but again, the actual format specifier strings can be used in many different languages.

Back to top A summary of printf format specifiers

Here's a quick summary of the available printf format specifiers:

%c character
%d decimal (integer) number (base 10)
%e exponential floating-point number
%f floating-point number
%i integer (base 10)
%o octal number (base 8)
%s a string of characters
%u unsigned decimal (integer) number
%x number in hexadecimal (base 16)
%% print a percent sign
\% print a percent sign
Back to top Controlling integer width with printf

The %3d specifier is used with integers, and means a minimum width of three spaces, which, by default, will be right-justified:

printf("%3d", 0); 0
printf("%3d", 123456789); 123456789
printf("%3d", -10); -10
printf("%3d", -123456789); -123456789
Back to top Left-justifying printf integer output

To left-justify integer output with printf , just add a minus sign ( - ) after the % symbol, like this:

printf("%-3d", 0); 0
printf("%-3d", 123456789); 123456789
printf("%-3d", -10); -10
printf("%-3d", -123456789); -123456789
Back to top The printf integer zero-fill option

To zero-fill your printf integer output, just add a zero ( 0 ) after the % symbol, like this:

printf("%03d", 0); 000
printf("%03d", 1); 001
printf("%03d", 123456789); 123456789
printf("%03d", -10); -10
printf("%03d", -123456789); -123456789
Back to top printf integer formatting

As a summary of printf integer formatting, here's a little collection of integer formatting examples. Several different options are shown, including a minimum width specification, left-justified, zero-filled, and also a plus sign for positive numbers.

Description Code Result
At least five wide printf("'%5d'", 10); ' 10'
At least five-wide, left-justified printf("'%-5d'", 10); '10 '
At least five-wide, zero-filled printf("'%05d'", 10); '00010'
At least five-wide, with a plus sign printf("'%+5d'", 10); ' +10'
Five-wide, plus sign, left-justified printf("'%-+5d'", 10); '+10 '
Back to top formatting floating point numbers with printf

Here are several examples showing how to format floating-point numbers with printf :

Description Code Result
Print one position after the decimal printf("'%.1f'", 10.3456); '10.3'
Two positions after the decimal printf("'%.2f'", 10.3456); '10.35'
Eight-wide, two positions after the decimal printf("'%8.2f'", 10.3456); ' 10.35'
Eight-wide, four positions after the decimal printf("'%8.4f'", 10.3456); ' 10.3456'
Eight-wide, two positions after the decimal, zero-filled printf("'%08.2f'", 10.3456); '00010.35'
Eight-wide, two positions after the decimal, left-justified printf("'%-8.2f'", 10.3456); '10.35 '
Printing a much larger number with that same format printf("'%-8.2f'", 101234567.3456); '101234567.35'
Back to top printf string formatting

Here are several examples that show how to format string output with printf :

Description Code Result
A simple string printf("'%s'", "Hello"); 'Hello'
A string with a minimum length printf("'%10s'", "Hello"); ' Hello'
Minimum length, left-justified printf("'%-10s'", "Hello"); 'Hello '
Back to top printf special characters

The following character sequences have a special meaning when used as printf format specifiers:

\a audible alert
\b backspace
\f form feed
\n newline, or linefeed
\r carriage return
\t tab
\v vertical tab
\\ backslash

As you can see from that last example, because the backslash character itself is treated specially, you have to print two backslash characters in a row to get one backslash character to appear in your output.

Here are a few examples of how to use these special characters:

Description Code Result
Insert a tab character in a string printf("Hello\tworld"); Hello world
Insert a newline character in a string printf("Hello\nworld"); Hello
world
Typical use of the newline character printf("Hello world\n"); Hello world
A DOS/Windows path with backslash characters printf("C:\\Windows\\System32\\"); C:\Windows\System32\
Back to top Related printf content

Here are a few links to other "printf" tutorials on my website:

And here's a link to the Java formatter javadoc .

Back to top java string source ruby reference printf perl java format cheatsheet c++ c scala sprintf books i've written
Comments

Submitted by Anonymoose (not verified) on November 5, 2009 - 10:36am

Permalink I have to commend you, you've I have to commend you, you've created a very easy to read manual on the basics of the printf function. That's a feat in and of itself. Bookmarked!

Submitted by Anonymous (not verified) on March 24, 2010 - 9:57pm

Permalink Cool Thanks this really helped ;)

Submitted by Anonymous (not verified) on June 11, 2010 - 9:10pm

Permalink Great job ! Thanks ! ^^

Submitted by alvin on October 9, 2010 - 6:15pm

Permalink printf formatting problems fixed Sorry for the long delay, but hopefully I've finally fixed the formatting problems with this article. If you see any errors please let me know, and I'll try to get them corrected.

Submitted by Anonymous (not verified) on November 7, 2010 - 5:37am

Permalink Neeeeat! :) Really helpful! :)

Submitted by Anonymous (not verified) on October 29, 2018 - 6:33am

Permalink Wonderful! Thank you! This is wonderfully easy to use. Links: front page alvin on twitter search privacy terms & conditions alvinalexander.com
is owned and operated by
Valley Programming, LLC

In regards to links to Amazon.com, As an Amazon Associate
I (Valley Programming, LLC) earn from qualifying purchases

This website uses cookies: learn more

java
java applets
java faqs
misc content
java source code
test projects
lejos
Perl
perl faqs
programs
perl recipes
perl tutorials
Unix
man (help) pages
unix by example
tutorials
source code
warehouse
java examples
drupal examples
misc
privacy policy
terms & conditions
subscribe
unsubscribe
wincvs tutorial
function point
analysis (fpa)
fpa tutorial
Other
contact me
rss feed
my photos
life in alaska
how i sold my business
living in talkeetna, alaska
my bookmarks
inspirational quotes
source code snippets
This website uses cookies: learn more

alvinalexander.com is owned and operated by Valley Programming, LLC

In regards to links to Amazon.com, "As an Amazon Associate
I (Valley Programming) earn from qualifying purchases"

[Dec 01, 2019] How can I export all subs in a Perl package?

Jan 01, 2009 | stackoverflow.com

Ask Question Asked 10 years, 7 months ago Active 3 years, 5 months ago Viewed 18k times


Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

[Dec 01, 2019] function - How can I export all subs in a Perl package - Stack Overflow

Jan 01, 2009 | stackoverflow.com

How can I export all subs in a Perl package? Ask Question Asked 10 years, 7 months ago Active 3 years, 5 months ago Viewed 18k times


Ville M ,

I would like to expose all subs into my namespace without having to list them one at a time:
@EXPORT = qw( firstsub secondsub third sub etc );

Using fully qualified names would require bunch of change to existing code so I'd rather not do that.

Is there @EXPORT_ALL?

I think documentation says it's a bad idea, but I'd like to do it anyway, or at least know how.

To answer Jon's why: right now for quick refactoring I want to move of bunch of subs into their own package with least hassle and code changes to the existing scripts (where those subs are currenty used and often repeated).

Also, mostly, I was just curious. (since it seemed like that Exporter might as well have that as standard feature, but somewhat surprisingly based on answers so far it doesn't)

brian d foy , 2009-04-08 23:58:35

Don't do any exporting at all, and don't declare a package name in your library. Just load the file with require and everything will be in the current package. Easy peasy.

Michael Carman , 2009-04-09 00:15:10

Don't. But if you really want to... write a custom import that walks the symbol table and export all the named subroutines.
# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

Chas. Owens ,

Warning, the code following is as bad an idea as exporting everything:
package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

Here is the some code that uses the module:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

And here is its output:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

Jon Ericson , 2009-04-08 22:33:36

You can always call subroutines in there fully-specified form:
MyModule::firstsub();

For modules I write internally, I find this convention works fairly well. It's a bit more typing, but tends to be better documentation.

Take a look at perldoc perlmod for more information about what you are trying to accomplish.

More generally, you could look at Exporter 's code and see how it uses glob aliasing. Or you can examine your module's namespace and export each subroutine. (I don't care to search for how to do that at the moment, but Perl makes this fairly easy.) Or you could just stick your subroutines in the main package:

 package main;
 sub firstsub() { ... }

(I don't think that's a good idea, but you know better than I do what you are trying to accomplish.)

There's nothing wrong with doing this provided you know what you are doing and aren't just trying to avoid thinking about your interface to the outside world.

ysth , 2009-04-09 01:29:04

Perhaps you would be interested in one of the Export* modules on CPAN that lets you mark subs as exportable simply by adding an attribute to the sub definition? (Don't remember which one it was, though.)

echo , 2014-10-11 18:23:01

https://metacpan.org/pod/Exporter::Auto

Exporter::Auto. this is all you need.

Tero Niemi , 2013-04-02 00:32:25

Although it is not usually wise to dump all sub s from module into the caller namespace, it is sometimes useful (and more DRY!) to automatically generate @EXPORT_OK and %EXPORT_TAGS variables.

The easiest method is to extend the Exporter. A simple example is something like this:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

Note the use of goto that removes us from the caller stack.

A more complete example can be found here: http://pastebin.com/Z1QWzcpZ It automatically generates tag groups from subroutine prefixes.

Sérgio , 2013-11-14 21:38:06

case 1

Library is :

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

you can use it, calling common:: :

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

common::onefunctionthatyoumadeonlibary()
case 2

Library is , yousimple export them :

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

use it in same "namespace":

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

Also we can do a mix of this two cases , we can export more common functions to use it without calling the packages name and other functions that we only call it with package name and that ones don't need to be exported.

> ,

You will have to do some typeglob munging. I describe something similar here:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

The import routine there should do exactly what you want -- just don't import any symbols into your own namespace.

[Nov 23, 2019] Static local variables in Perl

Jan 01, 2012 | stackoverflow.com

Ask Question Asked 7 years, 5 months ago Active 2 years, 8 months ago Viewed 12k times


Charles , 2012-05-31 20:50:19

I'm looking for advice on Perl best practices. I wrote a script which had a complicated regular expression:
my $regex = qr/complicated/;

# ...

sub foo {
  # ...

  if (/$regex/)
  # ...
}

where foo is a function which is called often, and $regex is not used outside that function. What is the best way to handle situations like this? I only want it to be interpreted once, since it's long and complicated. But it seems a bit questionable to have it in global scope since it's only used in that sub. Is there a reasonable way to declare it static?

A similar issue arises with another possibly-unjustified global. It reads in the current date and time and formats it appropriately. This is also used many times, and again only in one function. But in this case it's even more important that it not be re-initialized, since I want all instances of the date-time to be the same from a given invocation of the script, even if the minutes roll over during execution.

At the moment I have something like

my ($regex, $DT);

sub driver {
  $regex = qr/complicated/;
  $DT = dateTime();
  # ...
}

# ...

driver();

which at least slightly segregates it. But perhaps there are better ways.

Again: I'm looking for the right way to do this, in terms of following best practices and Perl idioms. Performance is nice but readability and other needs take priority if I can't have everything.

hobbs ,

If you're using perl 5.10+, use a state variable.
use feature 'state';
# use 5.010; also works

sub womble {
    state $foo = something_expensive();
    return $foo ** 2;
}

will only call something_expensive once.

If you need to work with older perls, then use a lexical variable in an outer scope with an extra pair of braces:

{
    my $foo = something_expensive();
    sub womble {
        return $foo ** 2;
    }
}

this keeps $foo from leaking to anyone except for womble .

ikegami , 2012-05-31 21:14:04

Is there any interpolation in the pattern? If not, the pattern will only be compiled once no matter how many times the qr// is executed.
$ perl -Mre=debug -e'qr/foo/ for 1..10' 2>&1 | grep Compiling | wc -l
1

$ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l
10

Even if there is interpolation, the pattern will only be compiled if the interpolated variables have changed.

$ perl -Mre=debug -e'$x=123; qr/foo$x/ for 1..10;' 2>&1 | grep Compiling | wc -l
1

$ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l
10

Otherwise, you can use

{
   my $re = qr/.../;
   sub foo {
      ...
      /$re/
      ...
   }
}

or

use feature qw( state );
sub foo {
   state $re = qr/.../;
   ...
   /$re/
   ...
}

Alan Rocker , 2014-07-02 16:25:27

Regexes can be specified with the "o" modifier, which says "compile pattern once only" - in the 3rd. edition of the Camel, see p. 147

zoul ,

There's a state keyword that might be a good fit for this situation:
sub foo {
    state $regex = /.../;
    ...
}

TrueY , 2015-01-23 10:14:12

I would like to complete ikegami 's great answer. Some more words I would like to waste on the definition of local variables in pre 5.10 perl .

Let's see a simple example code:

#!/bin/env perl 

use strict;
use warnings;

{ # local 
my $local = "After Crying";
sub show { print $local,"\n"; }
} # local

sub show2;

show;
show2;

exit;

{ # local 
my $local = "Solaris";
sub show2 { print $local,"\n"; }
} # local

The user would expect that both sub will print the local variable, but this is not true!

Output:

After Crying
Use of uninitialized value $local in print at ./x.pl line 20.

The reason is that show2 is parsed, but the initialization of the local variable is not executed! (Of course if exit is removed and a show2 is added at the end, Solaris will be printed in the thirds line)

This can be fixed easily:

{ # local 
my $local;
BEGIN { $local = "Solaris"; }
sub show2 { print $local,"\n"; }
} # local

And now the output what was expected:

After Crying
Solaris

But state in 5.10+ is a better choice...

I hope this helps!

[Nov 23, 2019] Introduction to Perl Modules

Nov 23, 2019 | ods.com.ua

CONTENTS


This chapter introduces you to the concepts behind references to Perl modules, packages, and classes. It also shows you how to create a few sample modules.

What Is a Perl Module?

A Perl module is a set of Perl code that acts like a library of function calls. The term module in Perl is synonymous with the word package . Packages are a feature of Perl 4, whereas modules are prevalent in Perl 5.

You can keep all your reusable Perl code specific to a set of tasks in a Perl module. Therefore, all the functionality pertaining to one type of task is contained in one file. It's easier to build an application on these modular blocks. Hence, the word module applies a bit more than package .

Here's a quick introduction to modules. Certain topics in this section will be covered in detail throughout the rest of the book. Read the following paragraphs carefully to get an overview of what lies ahead as you write and use your own modules.

What is confusing is that the terms module and package are used interchangeably in all Perl documentation, and these two terms mean the very same thing . So when reading Perl documents, just think "package" when you see "module" and vice versa.

So, what's the premise for using modules? Well, modules are there to package (pardon the pun) variables, symbols, and interconnected data items together. For example, using global variables with very common names such as $k , $j , or $i in a program is generally not a good idea. Also, a loop counter, $i , should be allowed to work independently in two different portions of the code. Declaring $i as a global variable and then incrementing it from within a subroutine will create unmanageable problems with your application code because the subroutine may have been called from within a loop that also uses a variable called $i . The use of modules in Perl allows variables with the same name to be created at different, distinct places in the same program.

The symbols defined for your variables are stored in an associative array, referred to as a symbol table . These symbol tables are unique to a package. Therefore, variables of the same name in two different packages can have different values.

Each module has its own symbol table of all symbols that are declared within it. The symbol table basically isolates synonymous names in one module from another. The symbol table defines a namespace , that is, a space for independent variable names to exist in. Thus, the use of modules, each with its own symbol table, prevents a variable declared in one section from overwriting the values of other variables with the same name declared elsewhere in the same program.

As a matter of fact, all variables in Perl belong to a package. The variables in a Perl program belong to the main package. All other packages within a Perl program either are nested within this main package or exist at the same level. There are some truly global variables, such as the signal handler array %SIG , that are available to all other modules in an application program and cannot be isolated via namespaces. Only those variable identifiers starting with letters or an underscore are kept in a module's symbol table. All other symbols, such as the names STDIN , STDOUT , STDERR , ARGV , ARGVOUT , ENV , Inc , and SIG are forced to be in package _main.

Switching between packages affects only namespaces. All you are doing when you use one package or another is declaring which symbol table to use as the default symbol table for lookup of variable names. Only dynamic variables are affected by the use of symbol tables. Variables declared by the use of the my keyword are still resolved with the code block they happen to reside in and are not referenced through symbol tables. In fact, the scope of a package declaration remains active only within the code block it is declared in. Therefore, if you switch symbol tables by using a package within a subroutine, the original symbol table in effect when the call was made will be restored when the subroutine returns.

Switching symbol tables affects only the default lookup of dynamic variable names. You can still explicitly refer to variables, file handles, and so on in a specific package by prepending a packageName :: to the variable name. You saw what a package context was when using references in Chapter 3 . A package context simply implies the use of the symbol table by the Perl interpreter for resolving variable names in a program. By switching symbol tables, you are switching the package context.

Modules can be nested within other modules. The nested module can use the variables and functions of the module it is nested within. For nested modules, you would have to use moduleName :: nestedModuleName and so on. Using the double colon ( :: ) is synonymous with using a back quote ( ` ). However, the double colon is the preferred, future way of addressing variables within modules.

Explicit addressing of module variables is always done with a complete reference. For example, suppose you have a module, Investment , which is the default package in use, and you want to address another module, Bonds , which is nested within the Investment module. In this case, you cannot use Bond:: . Instead, you would have to use Investment::Bond:: to address variables and functions within the Bond module. Using Bond:: would imply the use of a package Bond that is nested within the main module and not within the Investment module.

The symbol table for a module is actually stored in an associative array of the module's names appended with two colons. The symbol table for a module called Bond will be referred to as the associative array %Bond:: . The name for the symbol table for the main module is %main:: , and can even be shortened to %:: . Similarly, all nested packages have their symbols stored in associative arrays with double colons separating each nesting level. For example, in the Bond module that is nested within the Investment module, the associative array for the symbols in the Bond module will be named %Investment::Bond:: .

A typeglob is really a global type for a symbol name. You can perform aliasing operations by assigning to a typeglob . One or more entries in an associative array for symbols will be used when an assignment via a typeglob is used. The actual value in each entry of the associative array is what you are referring to when you use the * variableName notation. Thus, there are two ways of referring to variable names in a package:

*Investment::money = *Investment::bills;

$Investment::{'money'} = $Investment::{'bills'};

In the first method, you are referring to the variables via a typeglob reference. The use of the symbol table, %Investment:: , is implied here, and Perl will optimize the lookup for symbols money and bills . This is the faster and preferred way of addressing a symbol. The second method uses a lookup for the value of a variable addressed by 'money' and 'bills' in the associative array used for symbols, %Investment:: explicitly. This lookup would be done dynamically and will not be optimized by Perl. Therefore, the lookup will be forced to check the associative array every time the statement is executed. As a result, the second method is not efficient and should be used only for demonstration of how the symbol table is implemented internally.

Another example in this statement

*kamran = *husain;

causes variables, subroutines, and file handles that are named via the symbol kamran to also be addressed via the symbol husain . That is, all symbol entries in the current symbol table with the key kamran will now contain references to those symbols addressed by the key husain . To prevent such a global assignment, you can use explicit references. For example, the following statement will let you address the contents of $husain via the variable $kamran :

*kamran = \$husain;

However, any arrays such @kamran and @husain will not be the same. Only what the references specified explicitly will be changed. To summarize, when you assign one typeglob to another, you affect all the entries in a symbol table regardless of the type of variable being referred to. When you assign a reference from one variable type to another, you are only affecting one entry in the symbol table.

A Perl module file has the following format:

package ModuleName;
...
#### Insert module code ####
...
1;

The filename has to be called ModuleName.pm . The name of a module must end in the string .pm by convention. The package statement is the first line of the file. The last line of the file must contain the line with the 1; statement. This in effect returns a true value to the application program using the module. Not using the 1; statement will not let the module be loaded correctly.

The package statement tells the Perl interpreter to start with a new namespace domain. Basically, all your variables in a Perl script belong to a package called main . Every variable in the main package can be referred to as $main'variable .

Here's the syntax for such references:

$packageName'variableName

The single quote ( ' ) is synonymous with the double colon ( :: ) operator. I cover more uses of the :: operator in the next chapter. For the time being, you must remember that the following two statements are equivalent:

$packageName'variableName;
$packageName::variableName;

The double-colon syntax is considered standard in the Perl world. Therefore, to preserve readability, I use the double-colon syntax in the rest of this book unless it's absolutely necessary to make exceptions to prove a point.

The default use of a variable name defers to the current package active at the time of compilation. Thus, if you are in the package Finance.pm and specify a variable $pv , the variable is actually equal to $Finance::$pv .

Using Perl Modules: use vs. require

You include Perl modules in your program by using the use or the require statement. Here's the way to use either of these statements:

use ModuleName;
require ModuleName;

Note that the .pm extension is not used in the code shown above. Also note that neither statement allows a file to be included more than once in a program. The returned value of true ( 1; ) as the last statement is required to let Perl know that a require d or use d module loaded correctly and lets the Perl interpreter ignore any reloads. In general, it's better to use the use Module; statement than the require Module; statement in a Perl program to remain compatible with future versions of Perl.

For modules, you might want to consider continuing to use the require statement. Here's why: The use statement does a little bit more work than the require statement in that it alters the namespace of the module that includes another module. You want this extra update of the namespace to be done in a program. However, when writing code for a module, you may not want the namespace to be altered unless it's explicitly required. In this event, you will use the require statement.

The require statement includes the full pathname of a file in the @Inc array so that the functions and variables in the module's file are in a known location during execution time. Therefore, the functions that are imported from a module are imported via an explicit module reference at runtime with the require statement. The use statement does the same thing as the require statement because it updates the @Inc array with full pathnames of loaded modules. The code for the use function also goes a step further and calls an import function in the module being use d to explicitly load the list of exported functions at compile time, thus saving the time required for an explicit resolution of a function name during execution.

Basically, the use statement is equivalent to

require ModuleName; import ModuleName [list of imported functions];

The use of the use statement does change your program's namespace because the imported function names are inserted in the symbol table. The require statement does not alter your program's namespace. Therefore, the following statement

use ModuleName ();

is equivalent to this statement:

require ModuleName;

Functions are imported from a module via a call to a function called import . You can write your own import function in a module, or you can use the Exporter module and use its import function. In almost all cases, you will use the Exporter module to provide an import function instead of reinventing the wheel. (You'll learn more on this in the next section.) Should you decide not to use the Exporter module, you will have to write your own import function in each module that you write. It's much easier to simply use the Exporter module and let Perl do the work for you.

The Sample Letter.pm Module

The best way to illustrate the semantics of how a module is used in Perl is to write a simple module and show how to use it. Let's take the example of a local loan shark, Rudious Maximus, who is simply tired of typing the same "request for payment" letters. Being an avid fan of computers and Perl, Rudious takes the lazy programmer's approach and writes a Perl module to help him generate his memos and letters.

Now, instead of typing within fields in a memo template file, all he has to do is type a few lines to produce his nice, threatening note. Listing 4.1 shows you what he has to type.


Listing 4.1. Using the Letter module.
1 #!/usr/bin/perl -w
2 #
3 # Uncomment the line below to include the current dir in @Inc.
4 # push (@Inc, 'pwd');
5 #
6 use Letter;
7
8 Letter::To("Mr. Gambling Man","The money for Lucky Dog, Race 2");
9 Letter::ClaimMoneyNice();
10 Letter::ThankDem();
11 Letter::Finish();

The use Letter; statement is present to force the Perl interpreter to include the code for the module in the application program. The module should be located in the /usr/lib/perl5/ directory, or you can place it in any directory listed in the @Inc array. The @Inc array is the list of directories that the Perl interpreter will look for when attempting to load the code for the named module. The commented line (number 4) shows how to add the current working directory to include the path. The next four lines in the file generate the subject matter for the letter.

Here's the output from using the Letter module:

To: Mr. Gambling Man
Fm: Rudious Maximus, Loan Shark
Dt: Wed Feb 7 10:35:51 CST 1996

Re: The money for Lucky Dog, Race 2

====================================================

It has come to my attention that your account is
way over due.
You gonna pay us soon?
Or would you like me to come ovah?

Thanks for your support.

Sincerely,
Rudious

The Letter module file is shown in Listing 4.2. The name of the package is declared in the first line. Because this module's functions will be exported, I use the Exporter module. Therefore, the statement use Exporter; is required to inherit functionality from the Exporter module. Another required step is putting the word Exported in the @ISA array to allow searching for Exported.pm .

Note
The @ISA array is a special array within each package. Each item in the array lists where else to look for a method if it cannot be found in the current package. The order in which packages are listed in the @ISA array is the order in which Perl searches for unresolved symbols. A class that is listed in the @ISA array is referred to as the base class of that particular class. Perl will cache missing methods found in base classes for future references. Modifying the @ISA array will flush the cache and cause Perl to look up all methods again.

Let's now look at the code for Letter.pm in Listing 4.2.


Listing 4.2. The Letter.pm module.
1 package Letter;
2
3 require Exporter;
4 @ISA = (Exporter);
5
6 =head1 NAME
7
8 Letter - Sample module to generate letterhead for you
9
10 =head1 SYNOPSIS
11
12 use Letter;
13
14 Letter::Date();
15 Letter::To($name,$company,$address);
16
17 Then one of the following:
18 Letter::ClaimMoneyNice() {
19 Letter::ClaimMoney();
20 Letter::ThreatBreakLeg();
21
22 Letter::ThankDem();
23 Letter::Finish();
24
25 =head1 DESCRIPTION
26
27 This module provides a short example of generating a letter for a
28 friendly neighborbood loan shark.
29
30 The code begins after the "cut" statement.
31 =cut
32
33 @EXPORT = qw( Date,
34 To,
35 ClaimMoney,
36 ClaimMoneyNice,
37 ThankDem,
38 Finish );
39
40 #
41 # Print today's date
42 #
43 sub Letter::Date {
44 $date = 'date';
45 print "\n Today is $date";
46 }
47
48 sub Letter::To {
49 local($name) = shift;
50 local($subject) = shift;
51 print "\n To: $name";
52 print "\n Fm: Rudious Maximus, Loan Shark";
53 print "\n Dt: ", `date`;
54 print "\n Re: $subject";
55 print "\n\n";
56 print "\n====================================================\n";
57 }
58 sub Letter::ClaimMoney() {
59 print "\n You owe me money. Get your act together";
60 print "\n Do you want me to send Bruno over to ";
61 print "\n collect it , or are you gonna pay up?";
62 }
63
64 sub Letter::ClaimMoneyNice() {
65 print "\n It is come to my attention that your account is ";
66 print "\n way over due.";
67 print "\n You gonna pay us soon..";
68 print "\n or would you like me to come ovah?";
69 }
70
71 sub Letter::ThreatBreakLeg() {
72 print "\n apparently letters like these dont help";
73 print "\n I will have to make an example of you";
74 print "\n \n See you in the hospital, pal!";
75 }
76
77 sub Letter::ThankDem() {
78 print "\n\n Thanks for your support";
79 }
80
81 sub Letter::Finish(){
82 printf "\n\n\n\n Sincerely";
83 printf "\n Rudious \n ";
84 }
85
86 1;

Lines containing the equal sign are used for documentation. You must document each module for your own reference; Perl modules do not need to be documented, but it's a good idea to write a few lines about what your code does. A few years from now, you may forget what a module is about. Good documentation is always a must if you want to remember what you did in the past!

I cover documentation styles used for Perl in Chapter 8 , "Documenting Perl Scripts." For this sample module, the =head1 statement begins the documentation. Everything up to the =cut statement is ignored by the Perl interpreter.

Next, the module lists all the functions exported by this module in the @EXPORT array. The @EXPORT array defines all the function names that can be called by outside code. If you do not list a function in this @EXPORT array, it won't be seen by external code modules.

Following the @EXPORT array is the body of the code, one subroutine at a time. After all the subroutines are defined, the final statement 1; ends the module file. 1; must be the last executable line in the file.

Let's look at some of the functions defined in this module. The first function to look at is the simple Date function, lines 43 to 46, which prints the current UNIX date and time. There are no parameters to this function, and it doesn't return anything meaningful back to the caller.

Note the use of my before the $date variable in line 44. The my keyword is used to limit the scope of the variable to within the Date function's curly braces. Code between curly braces is referred to as a block . Variables declared within a block are limited in scope to within the curly braces. In 49 and 50, the local variables $name and $subject are visible to all functions.

You can also declare variables with the local qualifier. The use of local allows a variable to be in scope for the current block as well as for other blocks of code called from within this block. Thus, a local $x declared within one block is visible to all subsequent blocks called from within this block and can be referenced. In the following sample code, the ToTitled function's $name variable can be accessed but not the data in $iphone :

1 sub Letter::ToTitled {
2 local($name) = shift;
3 my($phone) = shift;
Subroutines and Passing Parameters

The sample code for Letter.pm showed how to extract one parameter at a time. The subroutine To() takes two parameters to set up the header for the memo.

Using functions within a module is not any different than using and defining Perl modules within the same code file. Parameters are passed by reference unless otherwise specified. Multiple arrays passed into a subroutine, if not explicitly dereferenced using the backslash, are concatenated.

The @_ input array in a function is always an array of scalar values. Passing values by reference is the preferred way in Perl to pass a large amount of data into a subroutine. ( See Chapter 3 , "References.")

Another Sample Module: Finance

The Finance module, shown in Listing 4.3, is used to provide simple calculations for loan values. Using the Finance module is straightforward. All the functions are written with the same parameters, as shown in the formula for the functions.

Let's look at how the future value of an investment can be calculated. For example, if you invest some dollars, $pv , in a bond that offers a fixed percentage rate, $r , applied at known intervals for $n time periods, what is the value of the bond at the time of its expiration? In this case, you'll be using the following formula:

$fv = $pv * (1+$r) ** $n ;

The function to get the future value is declared as FutureValue . Refer to Listing 4.3 to see how to use it.


Listing 4.3. Using the Finance module.
1 #!/usr/bin/perl -w
2
3 push(@Inc,'pwd');
4 use Finance;
5
6 $loan = 5000.00;
7 $apr = 3.5; # APR
8 $year = 10; # in years.
9
10 # ----------------------------------------------------------------
11 # Calculate the value at the end of the loan if interest
12 # is applied every year.
13 # ----------------------------------------------------------------
14 $time = $year;
15 $fv1 = Finance::FutureValue($loan,$apr,$time);
16 print "\n If interest is applied at end of year";
17 print "\n The future value for a loan of \$" . $loan . "\n";
18 print " at an APR of ", $apr , " for ", $time, " years";
19 printf " is %8.2f \n" , $fv1;
20
21 # ----------------------------------------------------------------
22 # Calculate the value at the end of the loan if interest
23 # is applied every month.
24 # ----------------------------------------------------------------
25 $rate = $apr / 12; # APR
26 $time = $year * 12; # in months
27 $fv2 = Finance::FutureValue($loan,$rate,$time);
28
29 print "\n If interest is applied at end of each month";
30 print "\n The future value for a loan of \$" . $loan . "\n";
31 print " at an APR of ", $apr , " for ", $time, " months";
32 printf " is %8.2f \n" , $fv2;
33
34 printf "\n The difference in value is %8.2f", $fv2 - $fv1;
35 printf "\n Therefore by applying interest at shorter time periods";
36 printf "\n we are actually getting more money in interest.\n";

Here is sample input and output of Listing 4.3.

$ testme

If interest is applied at end of year
The future value for a loan of $5000
at an APR of 3.5 for 10 years is 7052.99

If interest is applied at end of each month
The future value for a loan of $5000
at an APR of 3.5 for 120 months is 7091.72

The difference in value is 38.73
Therefore by applying interest at shorter time periods
we are actually getting more money in interest.

The revelation in the output is the result of the comparison of values between $fv1 and $fv2 . The $fv1 value is calculated with the application of interest once every year over the life of the bond. $fv2 is the value if the interest is applied every month at the equivalent monthly interest rate.

The Finance.pm package is shown in Listing 4.4 in its early development stages.


Listing 4.4. The Finance.pm package.
1 package Finance;
2
3 require Exporter;
4 @ISA = (Exporter);
5
6 =head1 Finance.pm
7
8 Financial Calculator - Financial calculations made easy with Perl
9
10 =head 2
11 use Finance;
12
13 $pv = 10000.0;
14
15 $rate = 12.5 / 12; # APR per month.
16
17 $time = 360 ; # months for loan to mature
18
19 $fv = FutureValue();
20
21 print $fv;
22
23 =cut
24
25 @EXPORT = qw( FutureValue,
26 PresentValue,
27 FVofAnnuity,
28 AnnuityOfFV,
29 getLastAverage,
30 getMovingAverage,
31 SetInterest);
32
33 #
34 # Globals, if any
35 #
36
37 local $defaultInterest = 5.0;
38
39 sub Finance::SetInterest($) {
40 my $rate = shift(@_);
41 $defaultInterest = $rate;
42 printf "\n \$defaultInterest = $rate";
43 }
44
45 # --------------------------------------------------------------------
46 # Notes:
47 # 1. The interest rate $r is given in a value of [0-100].
48 # 2. The $n given in the terms is the rate at which the interest
49 # is applied.
50 #
51 # --------------------------------------------------------------------
52
53 # --------------------------------------------------------------------
54 # Present value of an investment given
55 # fv - a future value
56 # r - rate per period
57 # n - number of period
58 # --------------------------------------------------------------------
59 sub Finance::FutureValue($$$) {
60 my ($pv,$r,$n) = @_;
61 my $fv = $pv * ((1 + ($r/100)) ** $n);
62 return $fv;
63 }
64
65 # --------------------------------------------------------------------
66 # Present value of an investment given
67 # fv - a future value
68 # r - rate per period
69 # n - number of period
70 # --------------------------------------------------------------------
71 sub Finance::PresentValue($$$) {
72 my $pv;
73 my ($fv,$r,$n) = @_;
74 $pv = $fv / ((1 + ($r/100)) ** $n);
75 return $pv;
76
77 }
78
79 # --------------------------------------------------------------------
80 # Get the future value of an annuity given
81 # mp - Monthly Payment of Annuity
82 # r - rate per period
83 # n - number of period
84 # --------------------------------------------------------------------
85
86 sub FVofAnnuity($$$) {
87 my $fv;
88 my $oneR;
89 my ($mp,$r,$n) = @_;
90
91 $oneR = ( 1 + $r) ** $n;
92 $fv = $mp * ( ($oneR - 1)/ $r);
93 return $fv;
94 }
95
96 # --------------------------------------------------------------------
97 # Get the annuity from the following bits of information
98 # r - rate per period
99 # n - number of period
100 # fv - Future Value
101 # --------------------------------------------------------------------
102
103 sub AnnuityOfFV($$$) {
104 my $mp; # mp - Monthly Payment of Annuity
105 my $oneR;
106 my ($fv,$r,$n) = @_;
107
108 $oneR = ( 1 + $r) ** $n;
109 $mp = $fv * ( $r/ ($oneR - 1));
110 return $mp;
111 }
112
113 # --------------------------------------------------------------------
114 # Get the average of the last "n" values in an array.
115 # --------------------------------------------------------------------
116 # The last $count number of elements from the array in @values
117 # The total number of elements in @values is in $number
118 #
119 sub getLastAverage($$@) {
120 my ($count, $number, @values) = @_;
121 my $i;
122
123 my $a = 0;
124 return 0 if ($count == 0);
125 for ($i = 0; $i< $count; $i++) {
126 $a += $values[$number - $i - 1];
127 }
128 return $a / $count;
129 }
130
131 # --------------------------------------------------------------------
132 # Get a moving average of the values.
133 # --------------------------------------------------------------------
134 # The window size is the first parameter, the number of items in the
135 # passed array is next. (This can easily be calculated within the
136 # function using the scalar() function, but the subroutine shown here
137 # is also being used to illustrate how to pass pointers.) The reference to the
138 # array of values is passed next, followed by a reference to the place
139 # the return values are to be stored.
140 #
141 sub getMovingAve($$\@\@) {
142 my ($count, $number, $values, $movingAve) = @_;
143 my $i;
144 my $a = 0;
145 my $v = 0;
146
147 return 0 if ($count == 0);
148 return -1 if ($count > $number);
149 return -2 if ($count < 2);
150
151 $$movingAve[0] = 0;
152 $$movingAve[$number - 1] = 0;
153 for ($i=0; $i<$count;$i++) {
154 $v = $$values[$i];
155 $a += $v / $count;
156 $$movingAve[$i] = 0;
157 }
158 for ($i=$count; $i<$number;$i++) {
159 $v = $$values[$i];
160 $a += $v / $count;
161 $v = $$values[$i - $count - 1];
162 $a -= $v / $count;
163 $$movingAve[$i] = $a;
164 }
165 return 0;
166 }
167
168 1;

Look at the declaration of the function FutureValue with ($$$) . The three dollar signs together signify three scalar numbers being passed into the function. This extra scoping is present for validating the type of the parameters passed into the function. If you were to pass a string instead of a number into the function, you would get a message very similar to this one:

Too many arguments for Finance::FutureValue at ./f4.pl line 15, near "$time)"
Execution of ./f4.pl aborted due to compilation errors.

The use of prototypes when defining functions prevents you from sending in values other than what the function expects. Use @ or % to pass in an array of values. If you are passing by reference, use \@ or \% to show a scalar reference to an array or hash, respectively. If you do not use the backslash, all other types in the argument list prototype are ignored. Other types of disqualifiers include an ampersand for a reference to a function, an asterisk for any type, and a semicolon to indicate that all other parameters are optional.

Now, let's look at the lastMovingAverage function declaration, which specifies two integers in the front followed by an array. The way the arguments are used in the function is to assign a value to each of the two scalars, $count and $number , whereas everything else is sent to the array. Look at the function getMovingAverage() to see how two arrays are passed in order to get the moving average on a list of values.

The way to call the getMovingAverage function is shown in Listing 4.5.


Listing 4.5. Using the moving average function.
1 #!/usr/bin/perl -w
2
3 push(@Inc,'pwd');
4 use Finance;
5
6 @values = ( 12,22,23,24,21,23,24,23,23,21,29,27,26,28 );
7 @mv = (0);
8 $size = scalar(@values);
9 print "\n Values to work with = { @values } \n";
10 print " Number of values = $size \n";
11
12 # ----------------------------------------------------------------
13 # Calculate the average of the above function
14 # ----------------------------------------------------------------
15 $ave = Finance::getLastAverage(5,$size,@values);
16 print "\n Average of last 5 days = $ave \n";
17
18 Finance::getMovingAve(5,$size,@values,@mv);
19 print "\n Moving Average with 5 days window = \n { @mv } \n";

Here's the output from Listing 4.5:

Values to work with = { 12 22 23 24 21 23 24 23 23 21 29 27 26 28 }
Number of values = 14

Average of last 5 days = 26.2

Moving Average with 5 days window =
{ 0 0 0 0 0 19.4 21.8 22 22 21.4 23 23.8 24.2 25.2 }

The getMovingAverage() function takes two scalars and then two references to arrays as scalars. Within the function, the two scalars to the arrays are dereferenced for use as numeric arrays. The returned set of values is inserted in the area passed in as the second reference. Had the input parameters not been specified with \@ for each referenced array, the $movingAve array reference would have been empty and would have caused errors at runtime. In other words, the following declaration is not correct:

sub getMovingAve($$@@)

The resulting spew of error messages from a bad function prototype is as follows:

Use of uninitialized value at Finance.pm line 128.
Use of uninitialized value at Finance.pm line 128.
Use of uninitialized value at Finance.pm line 128.
Use of uninitialized value at Finance.pm line 128.
Use of uninitialized value at Finance.pm line 128.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.
Use of uninitialized value at Finance.pm line 133.
Use of uninitialized value at Finance.pm line 135.

Values to work with = { 12 22 23 24 21 23 24 23 23 21 29 27 26 28 }
Number of values = 14

Average of last 5 days = 26.2

Moving Average with 5 days window =
{ 0 }

This is obviously not the correct output. Therefore, it's critical that you pass by reference when sending more than one array.

Global variables for use within the package can also be declared. Look at the following segment of code from the Finance.pm module to see what the default value of the Interest variable would be if nothing was specified in the input. (The current module requires the interest to be passed in, but you can change this.)

Here's a little snippet of code that can be added to the end of the program shown in Listing 4.5 to add the ability to set interest rates.

20 local $defaultInterest = 5.0;
21 sub Finance::SetInterest($) {
22 my $rate = shift(@_);
23 $rate *= -1 if ($rate < 0);
24 $defaultInterest = $rate;
25 printf "\n \$defaultInterest = $rate";
26 }

The local variable $defaultInterest is declared in line 20. The subroutine SetInterest to modify the rate is declared in lines 21 through 26. The $rate variable uses the values passed into the subroutine and simply assigns a positive value for it. You can always add more error checking if necessary.

To access the defaultInterest variable's value, you could define either a subroutine that returns the value or refer to the value directly with a call to the following in your application program:

$Finance::defaultInterest;
Returned Values from Subroutines in a Package

The variable holding the return value from the module function is declared as my variable . The scope of this variable is within the curly braces of the function only. When the called subroutine returns, the reference to my variable is returned. If the calling program uses this returned reference somewhere, the link counter on the variable is not zero; therefore, the storage area containing the returned values is not freed to the memory pool. Thus, the function that declares

my $pv

and then later returns the value of $pv returns a reference to the value stored at that location. If the calling routine performs a call like this one:

Finance::FVofAnnuity($monthly,$rate,$time);

there is no variable specified here into which Perl stores the returned reference; therefore, any returned value (or a list of values) is destroyed. Instead, the call with the returned value assigned to a local variable, such as this one:

$fv = Finance::FVofAnnuity($monthly,$rate,$time);

maintains the variable with the value. Consider the example shown in Listing 4.6, which manipulates values returned by functions.


Listing 4.6. Sample usage of the my function.
1 #!/usr/bin/perl -w
2
3 push(@Inc,'pwd');
4 use Finance;
5
6 $monthly = 400;
7 $rate = 0.2; # i.e. 6 % APR
8 $time = 36; # in months
9
10 print "\n# ------------------------------------------------";
11 $fv = Finance::FVofAnnuity($monthly,$rate,$time);
12 printf "\n For a monthly %8.2f at a rate of %%%6.2f for %d periods",
13 $monthly, $rate, $time;
14 printf "\n you get a future value of %8.2f ", $fv;
15
16 $fv *= 1.1; # allow 10 % gain in the house value.
17
18 $mo = Finance::AnnuityOfFV($fv,$rate,$time);
19
20 printf "\n To get 10 percent more at the end, i.e. %8.2f",$fv;
21 printf "\n you need a monthly payment value of %8.2f",$mo,$fv;
22
23 print "\n# ------------------------------------------------ \n";

Here is sample input and output for this function:

$ testme
# ------------------------------------------------
For a monthly 400.00 at a rate of % 0.20 for 36 periods
you get a future value of 1415603.75
To get 10 percent more at the end, i.e. 1557164.12
you need a monthly payment value of 440.00
# ------------------------------------------------
Multiple Inheritance

Modules implement classes in a Perl program that uses the object-oriented features of Perl. Included in object-oriented features is the concept of inheritance . (You'll learn more on the object-oriented features of Perl in Chapter 5 , "Object-Oriented Programming in Perl .") Inheritance means the process with which a module inherits the functions from its base classes. A module that is nested within another module inherits its parent modules' functions. So inheritance in Perl is accomplished with the :: construct. Here's the basic syntax:

SuperClass::NextSubClass:: ... ::ThisClass.

The file for these is stored in ./SuperClass/NextSubClass/ . Each double colon indicates a lower-level directory in which to look for the module. Each module, in turn, declares itself as a package with statements like the following:

package SuperClass::NextSubClass;
package SuperClass::NextSubClass::EvenLower;

For example, say that you really want to create a Money class with two subclasses, Stocks and Finance . Here's how to structure the hierarchy, assuming you are in the /usr/lib/perl5 directory:

  1. Create a Money directory under the /usr/lib/perl5 directory.
  2. Copy the existing Finance.pm file into the Money subdirectory.
  3. Create the new Stocks.pm file in the Money subdirectory.
  4. Edit the Finance.pm file to use the line package Money::Finance instead of package Finance; .
  5. Edit scripts to use Money::Finance as the subroutine prefix instead of Finance:: .
  6. Create a Money.pm file in the /usr/lib/perl5 directory.

The Perl script that gets the moving average for a series of numbers is presented in Listing 4.7.


Listing 4.7. Using inheriting modules.
1 #!/usr/bin/perl -w
2 $aa = 'pwd';
3 $aa .= "/Money";
4 push(@Inc,$aa);
5 use Money::Finance;
6 @values = ( 12,22,23,24,21,23,24,23,23,21,29,27,26,28 );
7 @mv = (0);
8 $size = scalar(@values);
9 print "\n Values to work with = { @values } \n";
10 print " Number of values = $size \n";
11 # ----------------------------------------------------------------
12 # Calculate the average of the above function
13 # ----------------------------------------------------------------
14 $ave = Money::Finance::getLastAverage(5,$size,@values);
15 print "\n Average of last 5 days = $ave \n";
16 Money::Finance::getMovingAve(5,$size,@values,@mv);
17 # foreach $i (@values) {
18 # print "\n Moving with 5 days window = $mv[$i] \n";
19 # }
20 print "\n Moving Average with 5 days window = \n { @mv } \n";

Lines 2 through 4 add the path to the Money subdirectory. The use statement in line 5 now addresses the Finance.pm file in the ./Money subdirectory. The calls to the functions within Finance.pm are now called with the prefix Money::Finance:: instead of Finance:: . Therefore, a new subdirectory is shown via the :: symbol when Perl is searching for modules to load.

The Money.pm file is not required. Even so, you should create a template for future use. Actually, the file would be required to put any special requirements for initialization that the entire hierarchy of modules uses. The code for initialization is placed in the BEGIN() function. The sample Money.pm file is shown in Listing 4.8.


Listing 4.8. The superclass module for Finance.pm .
1 package Money;
2 require Exporter;
3
4 BEGIN {
5 printf "\n Hello! Zipping into existence for you\n";
6 }
7 1;

To see the line of output from the printf statement in line 5, you have to insert the following commands at the beginning of your Perl script:

use Money;
use Money::Finance;

To use the functions in the Stocks.pm module, you use this line:

use Money::Stocks;

The Stocks.pm file appears in the Money subdirectory and is defined in the same format as the Finance.pm file, with the exceptions that use Stocks is used instead of use Finance and the set of functions to export is different.

The Perl Module Libraries

A number of modules are included in the Perl distribution. Check the /usr/lib/perl5/lib directory for a complete listing after you install Perl. There are two kinds of modules you should know about and look for in your Perl 5 release, Pragmatic and Standard modules.

Pragmatic modules, which are also like pragmas in C compiler directives, tend to affect the compilation of your program. They are similar in operation to the preprocessor elements of a C program. Pragmas are locally scoped so that they can be turned off with the no command. Thus, the command

no POSIX ;

turns off the POSIX features in the script. These features can be turned back on with the use statement.

Standard modules bundled with the Perl package include several functioning packages of code for you to use. Refer to appendix B, "Perl Module Archives," for a complete list of these standard modules.

To find out all the .pm modules installed on your system, issue the following command. (If you get an error, add the /usr/lib/perl5 directory to your path.)

find /usr/lib/perl5 -name perl "*.pm" -print
Extension Modules

Extension modules are written in C (or a mixture of Perl and C) and are dynamically loaded into Perl if and when you need them. These types of modules for dynamic loading require support in the kernel. Solaris lets you use these modules. For a Linux machine, check the installation pages on how to upgrade to the ELF format binaries for your Linux kernel.

What Is CPAN?

The term CPAN (Comprehensive Perl Archive Network) refers to all the hosts containing copies of sets of data, documents, and Perl modules on the Net. To find out about the CPAN site nearest you, search on the keyword CPAN in search engines such as Yahoo!, AltaVista, or Magellan. A good place to start is the www.metronet.com site .

Summary

This chapter introduced you to Perl 5 modules and described what they have to offer. A more comprehensive list is found on the Internet via the addresses shown in the Web sites http://www.metronet.com and http://www.perl.com .

A Perl package is a set of Perl code that looks like a library file. A Perl module is a package that is defined in a library file of the same name. A module is designed to be reusable. You can do some type checking with Perl function prototypes to see whether parameters are being passed correctly. A module has to export its functions with the @EXPORT array and therefore requires the Exporter module. Modules are searched for in the directories listed in the @Inc array.

Obviously, there is a lot more to writing modules for Perl than what is shown in this chapter. The simple examples in this chapter show you how to get started with Perl modules. In the rest of the book I cover the modules and their features, so hang in there.

I cover Perl objects, classes, and related concepts in Chapter 5 .

[Nov 23, 2019] min, max, sum in Perl using ListUtil

See also ListMoreUtils - Provide the stuff missing in ListUtil - metacpan.org
Nov 23, 2019 | perlmaven.com
List::Util module provides a number of simple and some more complex functions that can be used on lists, anything that returns a list anything that can be seen as a list.

For example these can be used on arrays as they "return their content" in list context . min

If given a list of numbers to it, it will return the smallest number:

examples/min.pl

  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( min );
  5. say min ( 10 , 3 , - 8 , 21 ); # -8
  6. my @prices = ( 17.2 , 23.6 , 5.50 , 74 , '10.3' );
  7. say min ( @prices ); # 5.5
  8. # Argument "2x" isn't numeric in subroutine entry at examples/min.pl line 14.
  9. say min ( 10 , 3 , '2x' , 21 ); # 2

If one of the arguments is a string that cannot be fully converted to a number automatically and if you have use warnings on as you should , then you'll see the following warnings: Argument ... isn't numeric in subroutine entry at ...

minstr

There is a corresponding function called minstr that will accept strings and sort them according to the ASCII order, though I guess it will work with Unicode as well if that's what you are feeding it.

examples/minstr.pl
  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( minstr );
  5. say minstr ( 'f' , 'b' , 'e' ); # b

It can also accept numbers as parameters and will treat them as strings. The result might surprise you, if you are not familiar with the automatic number to string conversion of Perl, and that the string "11" is ahead of the string "2" because the comparison works character-by-character and in this case the first character of "11" is ahead of the first (and only) character of "2" in the ASCII table.

examples/minstr_numbers.pl

  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( minstr );
  5. say minstr ( 2 , 11 , 99 ); # 11

After all internally it uses the lt operator.

max

Similar to min just returns the biggest number.

maxstr

Similar to minstr , returns the biggest string in ASCII order.

sum

The sum function adds up the provided numbers and returns their sum. If one or more of the values provided is a string that cannot be fully converted to a number it will generate a warning like this: Argument ... isn't numeric in subroutine entry at ... . If the parameters of sum are empty the function returns undef . This is unfortunate as it should be 0, but in order to provide backwards compatibility, if the provided list is empty then undef is returned.

examples/sum.pl

  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( sum );
  5. say sum ( 10 , 3 , - 8 , 21 ); # 26
  6. my @prices = ( 17.2 , 23.6 , '1.1' );
  7. say sum ( @prices ); # 41.9
  8. my @empty ;
  9. # Use of uninitialized value in say at examples/sum.pl line 14.
  10. say sum ( @empty ); # (prints nothing)
sum0

In order to fix the above issue, that sum() return undef , in version 1.26 of the module, in 2012, a new function called sum0 was introduced that behaves exactly like the sum function, but returns 0 if no values was supplied.

examples/sum0.pl

  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( sum0 );
  5. say sum0 ( 10 , 3 , - 8 , 21 ); # 26
  6. my @prices = ( 17.2 , 23.6 , '1.1' );
  7. say sum0 ( @prices ); # 41.9
  8. my @empty ;
  9. say sum0 ( @empty ); # 0
product

The product function multiplies its parameters. As this function is newer it was not constrained with backward compatibility issues so if the provided list is empty, the returned value will be 1.

examples/product.pl

  1. use 5.010 ;
  2. use strict ;
  3. use warnings ;
  4. use List :: Util qw ( product );
  5. my @interest = ( 1.2 , 2.6 , 4 , '1.3' );
  6. say product ( @interest ); # 16.224
  7. my @empty ;
  8. say product ( @empty ); # 1
Other functions of List::Util

The module has a number of other functions that were used in various other articles:

first

first returns the first element from a list that satisfies the given condition. For examples on how to use it an why is it good check out the articles Fast lookup by name or by date - Array - Hash - Linked List and Search for hash in an array of hashes .

any

The any function will return true if any of the given values satisfies the given condition. It is shown in the article Filtering values using Perl grep as a better solution.

It is also used in the example showing how to create a testing module and how to implement 'is_any' to test multiple expected values .

all

The all function will return true if all the supplied values satisfy the given condition. It can be seen in the article Check several regexes on many strings .

reduce

The reduce function might be familiar to you from the MapReduce programming model that was lauded around "BigData". It makes it provides a way to summarize data in an easy way. Implementing factorial in Perl - n! is a good and simple example. It is also used in the Fast lookup by name or by date - Array - Hash - Linked List article.

[Nov 21, 2019] Tux.nl - Style and Layout

Nov 21, 2019 | tux.nl

Why my style is best better

I will try to explain the logic behind the style decisions taken over that last 35+ years of programming in different languages.

About programming style and layout there are as many opinions as there are people. Most important in my opinion is to think about the reasoning behind what you, your team or your company chooses to follow as guides.

I seriously think that way too many (young) programmers leave school, brainwashed with GNU-style coding without realizing that the amount of indentation and the placing of braces, brackets and parentheses were well thought about.

Several well known styles (including mine) are discussed at wikimedia . It is worth reading through them to see the pros and cons of each.

For me personally, the GNU coding style is one of the reasons I do NOT contribute a lot to these projects. The style does not fit my logic, and if I send patches that are rejected simply because I wrote them in a style/layout that I think is way better because I then understand the underlying logic, I give up.

Here I will take a tour through what I think is the only correct way of (perl) code layout, and why. Most of this can be achieved with Perl::Tidy and a correct .perltidyrc . I'll use their configuration definitions as a guide.

Indentation in code blocks
Opening Block Brace Right or Left
Braces Left
Because braces are just syntactic sugar to keep a block together, it should visually also bind to the block, and not to the conditional. As the closing brace - or END in languages like PASCAL - is visually showing me the end of the block, it should obviously have the same indent as the block itself. An advantage is that the alignment of the closing brace with the block emphasizes the fact that the entire block is conceptually (as well as programmatically) a single compound statement.
In other words: I see the braces being part of the block, and as all statements inside a block share the same indentation, in my opinion the brace - being part of the block - should have the same indentation too.
  • Indent width is 4, tabs are allowed (when set to 8). I prefer having it being spaces only, but as I cannot see the difference with good editors, I do not really care.
  • Opening brace should be on the same line as the conditional
  • Block should be indented
  • Closing brace should have the same indent as the block
  if ($flag eq "a") {
      $anchor = $header;
      }
This style is also referred to as Ratliff style on wikipedia or Banner style on wikimedia.
Continuation Indentation
  if ($flag eq "a") {
      $anchor = substr ($header, 0, 6) .
                substr ($char_list, $place_1, 1) .
                substr ($char_list, $place_2, 1);
      }
Or, also acceptable:
  if ($flag eq "a") {
      $anchor =
          substr ($header, 0, 6) .
          substr ($char_list, $place_1, 1) .
          substr ($char_list, $place_2, 1);
      }
Braces Right
  if ($bigwasteofspace1 && $bigwasteofspace2 ||
      $bigwasteofspace3 && $bigwasteofspace4) {
      big_waste_of_time ();
      }
also acceptable:
  if (   $bigwasteofspace1 && $bigwasteofspace2
      || $bigwasteofspace3 && $bigwasteofspace4) {
      big_waste_of_time ();
      }
also acceptable:
  if (  $bigwasteofspace1 && $bigwasteofspace2 ||
        $bigwasteofspace3 && $bigwasteofspace4) {
      big_waste_of_time ();
      }
(No) Cuddled Else
Of course cuddled else is not the way to go, as it makes removing either branch more difficult and makes the indent of the closing brace go wrong. The only right way to use if/else indent is uncuddled:
  if ($flag eq "h") {
      $headers = 0;
      }
  elsif ($flag eq "f") {
      $sectiontype = 3;
      }
  else {
      print "invalid option: " . substr ($arg, $i, 1) . "\n";
      dohelp ();
      }
Vertical tightness
  sub _directives
  {
      {   ENDIF => \&_endif,
          IF    => \&_if,
          };
      } # _directives
the opening brace of a sub may optionally be put on a new line. If so, it should be in column one, for all those that use 'vi' or one of it's clones, so }, {, ]], and [[ work as expected.
if the opening brace is on the same line, which I prefer, it requires a single leading space
  sub _directives {
      {   ENDIF => \&_endif,
          IF    => \&_if,
          };
      } # _directives
Indentation Style for Other Containers
Opening Vertical Tightness
  $dbh = DBI->connect (undef, undef, undef, {
      PrintError => 0,
      RaiseError => 1,
      });
  if (!defined (start_slip ($DEVICE, $PHONE,  $ACCOUNT, $PASSWORD,
                            $LOCAL,  $REMOTE, $NETMASK, $MTU)) &&
       $continuation_flag) {
      do_something_about_it ();
      }
Closing Token Placement
  my @month_of_year = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
                        );
also acceptable:
  my @month_of_year = (qw(
      Jan Feb Mar Apr May Jun
      Jul Aug Sep Oct Nov Dec
      ));
As with the closing brace of a block, the closing parenthesis belongs to the data in the container it closes, and thus should have the same indentation.
Define Horizontal Tightness
Of course function <space> <paren> <no-space> <first-arg> <comma> <space>
  if ((my $duration = travel ($target, $means)) > 1200) {
One of my pet-peeves. Having white-space between the function name and its opening parenthesis is the best match to how we think. As an example, if I would ask someone to describe his/her day, he/she might answer
  I woke up
  I freshened myself
  I had breakfast
  I got to work
  I worked
  I had lunch
  I worked again
  I went home
  I had diner
  I watched TV
  I brushed my teeth
  I went to bed
In computer-speak
  wake_up ();
  wash ($self);
  eat ("breakfast");
  goto ("work")
  work ();
  eat ("lunch");
  work ();
  goto ("home");
  eat ("diner");
  watch_tv ();
  wash ($teeth);
  sleep ();
In which the seasoned programmer might see
  for $day in (qw( Mon Tue Wed Thu Fri )) {
     wake_up ();
     wash ($self);
     eat ("breakfast");
     :
     :
Or, more extreme to show the sequence of actions
  for $day in (qw( Mon Tue Wed Thu Fri )) {
     wake_up ();
     wash    ($self);
     eat     ("breakfast");
     :
     :
Where it, IMHO, clearly shows that the actions are far more important than what it takes to perform the action. When I read through the process, I don't care about what transport the person uses to get to work and if eggs are part of the breakfast. These are the parameters to the actions
  for $day in (qw( Mon Tue Wed Thu Fri )) {
     wake_up ();
     wash    ($day eq "Fri" ? "bath" : "shower", water_temp => "47");
     eat     (type   => "breakfast", eggs  => 2, toast => 4, Tea => "yes");
     travel  (target => $work,       means => "train");
     :
     :
I will only have a look at the function's argument if I need to. In reading that I eat , I see what action is taken. That's enough for understanding the program flow. The arguments to the function have to be grouped together using parenthesis for the function to know that all the arguments are for the function: the parenthesis are there to group the arguments, not to make the function a function so the parenthesis belong to the arguments and not to the function and therefor are to be close to the arguments ant not to the function.
Arguments are separated by a comma and a space, just to separate the arguments more for better readability
  my $width = $col[$j + $k] - $col[$j];

  my %bf = map { $_ => -M $_ } grep { m/\.deb$/ } dirents ".";
Statement modifiers
  $work_done and go_home ();
A rule of thumb is to NEVER use statement modifiers like
  go_home () unless $work_done; # WRONG!
As it will draw the attention to going home (unconditionally) instead of to the condition, which is more important. This is especially annoying when using exit, die, croak or return. Any of these will visually end the current scope, so you do not have to read on. Unless there is a statement modifier and you need to re-read the entire section.
No else after return/exit/die/croak/throw
  if (expression) {
      return;
      }
  else {
      return 42;
      }
As any of return, exit, die, croak, or throw will immediately exit the current scope, the mind will read the code as to stop processing it right there, which is exactly what those keywords are for.
In an if/else construct, the code after the construct is supposed to be executed when either if the if/else branches where followed. If the if-branch exits the current scope, there is no need to run the code after the construct, so the else is useless.
This is the main reason why these keywords should never have a statement modifier (and no, you cannot come up with a valid exception to this rule).
Statement Termination Semicolon Spaces
  my $i = 1;
For Loop Semicolon Spaces
  for (@a = @$ap, $u = shift @a; @a; $u = $v) {
Block Comment Indentation
  • If comment is aligned to the left margin, leave it there
  • If the original comment was indented, match the indent to the surrounding code.
  • Never reformat comments itself. Do not wrap
Outdenting Long Quotes
  if ($source_stream) {
      if (@ARGV > 0) {
          die "You may not specify any filenames when a source array is given\n";
          }
      }
  if ($source_stream) {
      if (@ARGV > 0) {
          die "You may not specify any filenames ".
              "when a source array is given\n";
          }
      }
  for (@methods) {
      push @results, {
          name => $_->name,
          help => $_->help,
          };
      }

[Nov 21, 2019] Replaying debugger commands from history

Nov 21, 2019 | perlmonks.org

LanX (Archbishop) on Nov 20, 2019 at 15:59 UTC

Re: Replaying debugger commands from history

Sure!

Have a look at the docs in perldebug#Debugger-Customization concerning

@DB::typeahead

like

sub afterinit { push @DB::typeahead, "b 4", "b 6"; }

IIRC it should be either settable

[Nov 21, 2019] Can the Perl debugger save the ReadLine history to a file?

Nov 21, 2019 | stackoverflow.com

Ask Question Asked 8 years, 5 months ago Active 6 years ago Viewed 941 times 10 2


eli ,Jun 7, 2018 at 14:13

I work quit a bit with lib ReadLine and the lib Perl Readline.

Yet, the Perl debugger refuses to save the session command line history.

Thus, each time I invoke the debugger I lose all of my previous history.

Does anyone know how to have the Perl debugger save, and hopefully, append session history similar to the bash HISTORYFILE ?

mirod ,Jun 22, 2011 at 10:31

The way I do this is by having the following line in my ~/.perldb file:

&parse_options("HistFile=$ENV{HOME}/.perldb.hist");

Debugger commands are then stored in ~/.perldb.hist and accessible across sessions.

ysth ,Jul 13, 2011 at 9:37

Add parse_options("TTY=/dev/stdin ReadLine=0"); to .perldb, then:
rlwrap -H .perl_history perl -d ...

mephinet ,Feb 21, 2012 at 12:37

$ export PERLDB_OPTS=HistFile=$HOME/.perldb.history

,

I did the following:

1) Created ~/.perldb , which did not exist previously.

2) Added &parse_options("HistFile=$ENV{HOME}/.perldb.hist"); from mirod's answer.

3) Added export PERLDB_OPTS=HistFile=$HOME/.perldb.history to ~/.bashrc from mephinet's answer.

4) Ran source .bashrc

5) Ran perl -d my program.pl , and got this warning/error

perldb: Must not source insecure rcfile /home/ics/.perldb.
        You or the superuser must be the owner, and it must not 
        be writable by anyone but its owner.

6) I protected ~/.perldb with owner rw chmod 700 ~/.perldb , and the error went away.

[Nov 15, 2019] Why is Perl so hated and still commonly used? And why should I learn it?

Notable quotes:
"... Per Damien Conway’s recommendations, I always unpack all the arguments from @_in the first line of a subroutine, which ends up looking just like a subroutine signature. (I almost never use shift for this purpose.) ..."
"... Perl bashing is largely hear-say. People hear something and they say it. It doesn't require a great deal of thought. ..."
"... It may not be as common as the usual gang of languages, but there's an enormous amount of work done in Perl. ..."
Nov 05, 2017 | www.quora.com

Joe Zbiciak , Employed Updated Nov 5 2017 · Author has 2k answers and 7.3m answer views

Perl bashing is popular sport among a particularly vocal crowd.

Perl is extremely flexible. Perl holds up TIMTOWTDI ( There Is More Than One Way To Do It ) as a virtue. Larry Wall's Twitter handle is @TimToady, for goodness sake!

That flexibility makes it extremely powerful. It also makes it extremely easy to write code that nobody else can understand. (Hence, Tim Toady Bicarbonate.)

You can pack a lot of punch in a one-liner in Perl:

  1. print $fo map { sprintf ( " .pword 0x%.6X\n" , $_ ) } unpack ( "n*" , $data );

That one-liner takes a block of raw data (in $data ), expands it to an array of values, and th...

Joachim Pense , Perl is my language of choice Answered Nov 4, 2017 · Author has 6.1k answers and 7.1m answer views

It is still used, but its usage is declining. People use Python today in situations when they would have used Perl ten years ago.

The problem is that Perl is extremely pragmatic. It is designed to be “a language to get your job done”, and it does that well; however, that led to rejection by language formalists. However, Perl is very well designed, only it is well designed for professionals who grab in the dark expecting that at this place there should be a button to do the desired functionality, and indeed, there will be the button. It is much safer to use than for example C (the sharp knife that was delivered without a handle), but it is easy to produce quite messy code with it if you are a newbie who doesn’t understand/feel the principles of Perl. In the 90s and 2000s, it was the goto web language, so the web was full of terrible programs written by those newbies, and that led to the bad reputation.

Strangely enough, PHP, which is frowned upon a lot by Perl programmers, won the favour of the noobs, but never got the general bad reputation; in fact it is missing the design principles I mentioned, that language is just a product of adhockery.

But today, Perl went back to its status as a niche language, and you cannot mention it in presence of a lady, so to speak. Its support is slowly waning; I’d suggest to learn Python, but don’t force me to learn it as well.

John Robinson , Software Engineer Answered Nov 4, 2017 · Author has 416 answers and 92.9k answer views

You should learn things that make your life easier or better. I am not an excellent Perl user, but it is usually my go-to scripting language for important projects. The syntax is difficult, and it's very easy to forget how to use it when you take significant time away from it.

That being said, I love how regular expressions work in Perl. I can use sed like commands $myvar =~ s/old/new/g for string replacement when processing or filtering strings. It's much nicer than other languages imo.

I also like Perls foreach loops and its data structures.

I tried writing a program of moderate length in Python and it just seemed to be taking up too much space. I stopped part way though and switched to Perl. I got the whole thing completed in much less space (lines), and seemed to have an easier time doing it.

I am not a super fanboy, but it has just always worked for me in the past, and I can't outright discount it because of that.

Also, look up CPAN modules. The installation of those for me on GNU is a breeze.

My last scripting project I did in Python and it went very well. I will probably shift to Python more in the future, because I would like to build a stronger basis of knowledge with the modules and basics of Python so that I can hop into it and create some powerful stuff when needed. Ie I want to focus on 1–3 languages, and learn them to a higher level instead of being "just ok" with 5–7.

Gary Puckering , Fluent in C#, Python, and perl; rusty in C/C++ and too many others to count Answered Apr 25, 2018 · Author has 1.1k answers and 2.5m answer views

Why is Perl so hated and not commonly used?

I think there are several reasons why Perl has a lot of detractors

  1. Sigils . A lot of programmers seem to hate the $@% sigils! If you are coming from a strongly typed language like C/C++, and also hate things like Hungarian notation, you won’t like sigils.
  2. One liners. As others have commented, writing dense and even obfuscated code rose to the level of sport within the Perl community. The same thing happened, years earlier, in the APL community. Programmers and managers saw that you could write unmaintainable code, and that helped instill a fear that it was unavoidable and that perhaps the language was flawed because it didn’t discourage the practice.
  3. Auto-magic . The programming language PL/I, which attempted to combine the best of COBOL and FORTRAN, went absolutely crazy with default behaviors. I remember reading an article in the 1970’s where programming in PL/I was described as being like flying a Boeing 747. The cockpit is filled with hundreds of buttons, knobs, switches and levers. The autopilot does most of the work, but trying to figure out the interaction between it and things you manually set can be bewildering. Perl, to some extent, suffers from the same problem. In Perl 5, without enabling warnings and strict, variables spring into life simply by naming them. A typo can instantiate and entirely new variable. Hashes get new keys simply by an attempt to access a key. You can increment a scalar that contains a string and it’ll try to generate a sequence using the string as a pattern (e.g. a, b, c … z, aa, ab …). If you come from a language where you control everything, all this auto-magic stuff can really bite you in the ass.
  4. An odd object-oriented syntax. Until Moose (and now Moo and Mouse) came along, writing classes in Perl meant using keywords like package and bless, as well as rolling all your own accessor methods. If you come from C++, Java , Python or just about any other language supporting OO your first question is going to be: where’s the friggin’ class statement!
  5. Dynamic typing . Some people like it. Some hate it. There are modules that let you add typing I’d you wish, though it’ll only be enforced at run time.
  6. No subroutine signatures . Although Perl 5 now supports subroutine signatures, they are still considered “experimental”. This is a turn-off for most programmers who are used to them. Per Damien Conway’s recommendations, I always unpack all the arguments from @_in the first line of a subroutine, which ends up looking just like a subroutine signature. (I almost never use shift for this purpose.)
  7. Lots of magic symbols . Although you can use English names, and should do so for more maintainable code, many Perl programmers stick to using special names like $_, $’, $; etc. This makes Perl code look very cryptic, and increases your cognitive load when working with the language. It’s a lot to remember. But if you use the English names, you can largely avoid this issue.
  8. Perl 6 is a discontinuous evolution . Although Perl 5 continues to evolve, and some of the advances that have been put in Perl 6 have been added to Perl 5, the lack of,upward compatibility between 5 and 6 creates uncertainly about its future.

And why should I learn it?

Despite the above, you can write maintainable code in Perl by following Damian Comways’s Perl Best Practices. The utility perlcritic can be used to help train yourself to write better Perl code.

Perl is multi-paradigm. In execution, it’s faster than Python. It has a superb ecosystem in cpan , where you can find a module to help you solve almost every imaginable problem. For command line utilities, file system administration, database administration, data extraction-transformation-loading tasks, batch processes, connecting disparate systems, and quick and dirty scripts, it’s often the best tool for the job.

I frequently use Perl in connection with Excel. You can do a lot in Excel, and it provides a great interactive UI. But complex formulas can be a pain to get right, and it can be tedious to write code in VBA. Often, I find it much quicker to just copy cells to the clipboard, switch to a command shell, run a Perl script over the data, sending the results to the clipboard, switch back to Excel, and then paste the results in situ or in a new location.

Perl is also deep. It does a good job of supporting imperative programming, OOP, and functional programming. For more on the latter, see the book Higher-Order Perl .

Perl is powerful. Perl is fast. Perl is an effective tool to have in your toolkit. Those are all good reasons to learn it.

Reed White , former Engineer at Hewlett-Packard (1978-2000) Answered Nov 7, 2017 · Author has 2.3k answers and 380.8k answer views

Yes, Perl takes verbal abuse; but in truth, it is an extremely powerful, reliable language. In my opinion, one of its outstanding characteristics is that you don't need much knowledge before you can write useful programs. As time goes by, you gradually learn the real power of the language.

However, because Perl-bashing is popular, you might better put your efforts into learning Python, which is also quite capable.

Richard Conto , Programmer in multiple languages. Debugger in even more Answered Dec 18, 2017 · Author has 5.9k answers and 4.3m answer views

Perl bashing is largely hear-say. People hear something and they say it. It doesn't require a great deal of thought.

As for Perl not commonly being used - that's BS. It may not be as common as the usual gang of languages, but there's an enormous amount of work done in Perl.

As for you you should learn Perl, it's for the same reason you would learn any other language - it helps you solve a particular problem better than another language available. And yes, that can be a very subjective decision to make.

Randal L. Schwartz , Literally "wrote the books" on it Answered Mar 3, 2018 · Author has 108 answers and 90.5k answer views

The truth is, that by any metric, more Perl is being done today than during the dot com boom. It's just a somewhat smaller piece of a much bigger pie. In fact, I've heard from some hiring managers that there's actually a shortage of Perl programmers, and not just for maintaining projects, but for new greenfield deploys.

[Nov 14, 2019] perl - package variable scope in module subroutine - Stack Overflow

Nov 14, 2019 | stackoverflow.com

package variable scope in module subroutine Ask Question Asked 7 years, 7 months ago Active 7 years, 7 months ago Viewed 20k times 8 1


brian d foy ,Jul 17, 2014 at 17:54

How do I change the value of a variable in the package used by a module so that subroutines in that module can use it?

Here's my test case:

testmodule.pm:

package testmodule;

use strict;
use warnings;
require Exporter;

our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);

@ISA = qw(Exporter);
@EXPORT = qw(testsub);

my $greeting = "hello testmodule";
my $var2;

sub testsub {
    printf "__PACKAGE__: %s\n", __PACKAGE__;
    printf "\$main::greeting: %s\n", $main::greeting;
    printf "\$greeting: %s\n", $greeting;
    printf "\$testmodule::greeting: %s\n", $testmodule::greeting;
    printf "\$var2: %s\n", $var2;
} # End testsub
1;

testscript.pl:

#!/usr/bin/perl -w
use strict;
use warnings;
use testmodule;

our $greeting = "hello main";
my $var2 = "my var2 in testscript";

$testmodule::greeting = "hello testmodule from testscript";
$testmodule::var2 = "hello var2 from testscript";

testsub();

output:

Name "testmodule::var2" used only once: possible typo at ./testscript.pl line 11.
__PACKAGE__: testmodule
$main::greeting: hello main
$greeting: hello testmodule
$testmodule::greeting: hello testmodule from testscript
Use of uninitialized value $var2 in printf at testmodule.pm line 20.
$var2:

I expected $greeting and $testmodule::greeting to be the same since the package of the subroutine is testmodule .

I guess this has something to do with the way use d modules are eval d as if in a BEGIN block, but I'd like to understand it better.

I was hoping to set the value of the variable from the main script and use it in the module's subroutine without using the fully-qualified name of the variable.

perl-user ,Sep 5, 2013 at 13:58

As you found out, when you use my , you are creating a locally scoped non-package variable. To create a package variable, you use our and not my :
my $foo = "this is a locally scoped, non-package variable";
our $bar = "This is a package variable that's visible in the entire package";

Even better:

{
   my $foo = "This variable is only available in this block";
   our $bar = "This variable is available in the whole package":
}

print "$foo\n";    #Whoops! Undefined variable
print "$bar\n";    #Bar is still defined even out of the block

When you don't put use strict in your program, all variables defined are package variables. That's why when you don't put it, it works the way you think it should and putting it in breaks your program.

However, as you can see in the following example, using our will solve your dilemma:

File Local/Foo.pm
#! /usr/local/bin perl
package Local::Foo;

use strict;
use warnings;
use feature qw(say);

use Exporter 'import';
our @EXPORT = qw(testme);

our $bar = "This is the package's bar value!";
sub testme {

    # $foo is a locally scoped, non-package variable. It's undefined and an error
    say qq(The value of \$main::foo is "$main::foo");

    # $bar is defined in package main::, and will print out
    say qq(The value of \$main::bar is "$main::bar");

    # These both refer to $Local::Foo::bar
    say qq(The value of \$Local::Foo::bar is "$Local::Foo::bar");
    say qq(The value of bar is "$bar");
}

1;
File test.pl
#! /usr/local/bin perl
use strict;
use warnings;
use feature qw(say);
use Local::Foo;

my $foo = "This is foo";
our $bar = "This is bar";
testme;

say "";
$Local::Foo::bar = "This is the NEW value for the package's bar";
testme

And, the output is:

Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the package's bar value!"
The value of bar is "This is the package's bar value!"

Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the NEW value for the package's bar"
The value of bar is "This is the NEW value for the package's bar"

The error message you're getting is the result of $foo being a local variable, and thus isn't visible inside the package. Meanwhile, $bar is a package variable and is visible.

Sometimes, it can be a bit tricky:

if ($bar -eq "one") {
   my $foo = 1;
}
else {
   my $foo = 2;
}

print "Foo = $foo\n";

That doesn't work because $foo only bas a value inside the if block. You have to do this:

my $foo;
if ($bar -eq "one") {
   $foo = 1;
}
else {
  $foo = 2;
}

print "Foo = $foo\n"; #This works!

Yes, it can be a bit to get your head wrapped around it initially, but the use of use strict; and use warnings; is now de rigueur and for good reasons. The use of use strict; and use warnings; probably has eliminated 90% of the mistakes people make in Perl. You can't make a mistake of setting the value of $foo in one part of the program, and attempting to use $Foo in another. It's one of the things I really miss in Python.

> ,

After reading Variable Scoping in Perl: the basics more carefully, I realized that a variable declared with my isn't in the current package. For example, in a simple script with no modules if I declare my $var = "hello" $main::var still doesn't have a value.

The way that this applies in this case is in the module. Since my $greeting is declared in the file, that hides the package's version of $greeting and that's the value which the subroutine sees. If I don't declare the variable first, the subroutine would see the package variable, but it doesn't get that far because I use strict .

If I don't use strict and don't declare my $greeting , it works as I would have expected. Another way to get the intended value and not break use strict is to use our $greeting . The difference being that my declares a variable in the current scope while our declares a variable in the current package .

[Nov 13, 2019] How fast is Perl s smartmatch operator when searching for a scalar in an array

Nov 13, 2019 | stackoverflow.com

Paul Tomblin ,Oct 19, 2010 at 13:38

I want to repeatedly search for values in an array that does not change.

So far, I have been doing it this way: I put the values in a hash (so I have an array and a hash with essentially the same contents) and I search the hash using exists .

I don't like having two different variables (the array and the hash) that both store the same thing; however, the hash is much faster for searching.

I found out that there is a ~~ (smartmatch) operator in Perl 5.10. How efficient is it when searching for a scalar in an array?

> ,

If you want to search for a single scalar in an array, you can use List::Util 's first subroutine. It stops as soon as it knows the answer. I don't expect this to be faster than a hash lookup if you already have the hash , but when you consider creating the hash and having it in memory, it might be more convenient for you to just search the array you already have.

As for the smarts of the smart-match operator, if you want to see how smart it is, test it. :)

There are at least three cases you want to examine. The worst case is that every element you want to find is at the end. The best case is that every element you want to find is at the beginning. The likely case is that the elements you want to find average out to being in the middle.

Now, before I start this benchmark, I expect that if the smart match can short circuit (and it can; its documented in perlsyn ), that the best case times will stay the same despite the array size, while the other ones get increasingly worse. If it can't short circuit and has to scan the entire array every time, there should be no difference in the times because every case involves the same amount of work.

Here's a benchmark:

#!perl
use 5.12.2;
use strict;
use warnings;

use Benchmark qw(cmpthese);

my @hits = qw(A B C);
my @base = qw(one two three four five six) x ( $ARGV[0] || 1 );

my @at_end       = ( @base, @hits );
my @at_beginning = ( @hits, @base );

my @in_middle = @base;
splice @in_middle, int( @in_middle / 2 ), 0, @hits;

my @random = @base;
foreach my $item ( @hits ) {
    my $index = int rand @random;
    splice @random, $index, 0, $item;
    }

sub count {
    my( $hits, $candidates ) = @_;

    my $count;
    foreach ( @$hits ) { when( $candidates ) { $count++ } }
    $count;
    }

cmpthese(-5, {
    hits_beginning => sub { my $count = count( \@hits, \@at_beginning ) },
    hits_end       => sub { my $count = count( \@hits, \@at_end ) },
    hits_middle    => sub { my $count = count( \@hits, \@in_middle ) },
    hits_random    => sub { my $count = count( \@hits, \@random ) },
    control        => sub { my $count = count( [], [] ) },
  }
);
div class="answercell post-layout--right

,

Here's how the various parts did. Note that this is a logarithmic plot on both axes, so the slopes of the plunging lines aren't as close as they look:

So, it looks like the smart match operator is a bit smart, but that doesn't really help you because you still might have to scan the entire array. You probably don't know ahead of time where you'll find your elements. I expect a hash will perform the same as the best case smart match, even if you have to give up some memory for it.


Okay, so the smart match being smart times two is great, but the real question is "Should I use it?". The alternative is a hash lookup, and it's been bugging me that I haven't considered that case.

As with any benchmark, I start off thinking about what the results might be before I actually test them. I expect that if I already have the hash, looking up a value is going to be lightning fast. That case isn't a problem. I'm more interested in the case where I don't have the hash yet. How quickly can I make the hash and lookup a key? I expect that to perform not so well, but is it still better than the worst case smart match?

Before you see the benchmark, though, remember that there's almost never enough information about which technique you should use just by looking at the numbers. The context of the problem selects the best technique, not the fastest, contextless micro-benchmark. Consider a couple of cases that would select different techniques:

Now, keeping those in mind, I add to my previous program:

my %old_hash = map {$_,1} @in_middle; 

cmpthese(-5, {
    ...,
    new_hash       => sub { 
        my %h = map {$_,1} @in_middle; 
        my $count = 0;
        foreach ( @hits ) { $count++ if exists $h{$_} }
        $count;
        },
    old_hash       => sub { 
        my $count = 0;
        foreach ( @hits ) { $count++ if exists $old_hash{$_} }
        $count;
        },
    control_hash   => sub { 
        my $count = 0;
        foreach ( @hits ) { $count++ }
        $count;
        },
    }
);

Here's the plot. The colors are a bit difficult to distinguish. The lowest line there is the case where you have to create the hash any time you want to search it. That's pretty poor. The highest two (green) lines are the control for the hash (no hash actually there) and the existing hash lookup. This is a log/log plot; those two cases are faster than even the smart match control (which just calls a subroutine).

There are a few other things to note. The lines for the "random" case are a bit different. That's understandable because each benchmark (so, once per array scale run) randomly places the hit elements in the candidate array. Some runs put them a bit earlier and some a bit later, but since I only make the @random array once per run of the entire program, they move around a bit. That means that the bumps in the line aren't significant. If I tried all positions and averaged, I expect that "random" line to be the same as the "middle" line.

Now, looking at these results, I'd say that a smart-match is much faster in its worst case than the hash lookup is in its worst case. That makes sense. To create a hash, I have to visit every element of the array and also make the hash, which is a lot of copying. There's no copying with the smart match.

Here's a further case I won't examine though. When does the hash become better than the smart match? That is, when does the overhead of creating the hash spread out enough over repeated searches that the hash is the better choice?

,

Fast for small numbers of potential matches, but not faster than the hash. Hashes are really the right tool for testing set membership. Since hash access is O(log n) and smartmatch on an array is still O(n) linear scan (albeit short-circuiting, unlike grep), with larger numbers of values in the allowed matches, smartmatch gets relatively worse. Benchmark code (matching against 3 values):
#!perl
use 5.12.0;
use Benchmark qw(cmpthese);

my @hits = qw(one two three);
my @candidates = qw(one two three four five six); # 50% hit rate
my %hash;
@hash{@hits} = ();

sub count_hits_hash {
  my $count = 0;
  for (@_) {
    $count++ if exists $hash{$_};
  }
  $count;
}

sub count_hits_smartmatch {
  my $count = 0;
  for (@_) {
    $count++ when @hits;
  }
  $count;
}

say count_hits_hash(@candidates);
say count_hits_smartmatch(@candidates);

cmpthese(-5, {
    hash => sub { count_hits_hash((@candidates) x 1000) },
    smartmatch => sub { count_hits_smartmatch((@candidates) x 1000) },
  }
);
Benchmark results:
             Rate smartmatch       hash
smartmatch  404/s         --       -65%
hash       1144/s       183%         --

[Nov 13, 2019] Static code analysis module in Perl - Stack Overflow

Nov 13, 2019 | stackoverflow.com

Static code analysis module in Perl Ask Question Asked 7 years, 5 months ago Active 1 year, 7 months ago Viewed 835 times 0

DavidO ,Jun 12, 2012 at 9:13

Is there any static code analysis module in Perl except B::Lint and Perl::Critic? How effective is Module::Checkstyle?

> ,

There is a post on perlmonks.org asking if PPI can be used for static analysis. PPI is the power behind Perl::Critic, according to the reviews of this module. (I have not used it yet).

Then there is perltidy .

[Nov 12, 2019] lib-Module-Checkstyle.pm

Nov 12, 2019 | metacpan.org

Module::Checkstyle is a tool similar to checkstyle http://checkstyle.sourceforge.net for Java. It allows you to validate that your code confirms to a set of guidelines checking various things such as indentation, naming, whitespace, complexity and so forth.

Module::Checkstyle is also extensible so your organization can implement custom checks that are not provided by the standard distribution. There is a guide on how to write checks in Module::Checkstyle::Check

Module::Checkstyle is mostly used via the provided module-checkstyle tool. You probablly want to read module-checkstyle .

NAME

module-checkstyle - Check that your code keeps style

SYNOPSIS

module-checkstyle [options] [file and directories ...]

This program is the command-line interface to Module::Checkstyle .

You invoke it by supplying a list of files or directories that contain Perl code that should be checked aginst the configuration. Any problems found will be reported on standard out.

OPTIONS
-help
Print a brief help message and exits.
-man
Prints the manual page and exists.
-config
Use an alternate config file instead of ~/.module-checkstyle/config .
-all
Don't ignore common files when traversing directories. Common files are things such as blib/* t/* Makefile.PL etc.
-debug
Turn on debugging information.
-version
Display version information.

[Nov 12, 2019] Static code analysis module in Perl - Stack Overflow

Nov 12, 2019 | stackoverflow.com

Static code analysis module in Perl Ask Question Asked 7 years, 5 months ago Active 1 year, 7 months ago Viewed 835 times 0

DavidO ,Jun 12, 2012 at 9:13

Is there any static code analysis module in Perl except B::Lint and Perl::Critic? How effective is Module::Checkstyle?

> ,

There is a post on perlmonks.org asking if PPI can be used for static analysis. PPI is the power behind Perl::Critic, according to the reviews of this module. (I have not used it yet).

Then there is perltidy .

[Nov 12, 2019] lib-Module-Checkstyle.pm - metacpan.org

Nov 12, 2019 | metacpan.org

Module::Checkstyle is a tool similar to checkstyle http://checkstyle.sourceforge.net for Java. It allows you to validate that your code confirms to a set of guidelines checking various things such as indentation, naming, whitespace, complexity and so forth.

Module::Checkstyle is also extensible so your organization can implement custom checks that are not provided by the standard distribution. There is a guide on how to write checks in Module::Checkstyle::Check

Module::Checkstyle is mostly used via the provided module-checkstyle tool. You probablly want to read module-checkstyle .

NAME

module-checkstyle - Check that your code keeps style

SYNOPSIS

module-checkstyle [options] [file and directories ...]

This program is the command-line interface to Module::Checkstyle .

You invoke it by supplying a list of files or directories that contain Perl code that should be checked aginst the configuration. Any problems found will be reported on standard out.

OPTIONS
-help
Print a brief help message and exits.
-man
Prints the manual page and exists.
-config
Use an alternate config file instead of ~/.module-checkstyle/config .
-all
Don't ignore common files when traversing directories. Common files are things such as blib/* t/* Makefile.PL etc.
-debug
Turn on debugging information.
-version
Display version information.

[Nov 11, 2019] How fast is Perl's smartmatch operator when searching for a scalar in an array - Stack Overflow

Nov 11, 2019 | stackoverflow.com

[Nov 10, 2019] With the rename from Perl 6 to Racu chances of mass adoption of the new language probably evaporated

Racu now needs to compete on its own merits with established languages which is extremely difficult as Ruby and Python covers the same application area
This is a positive decision for Perl5 as it slowly returns to its main niche -- the tool for advanced Unix sysadmins. Still as the decision was made rather late in language development cycle itt will negativly affect Racu future, if it has any. The main interest in the new language was because of the name -- Perl6. No this is gone.
It also split the community into Perl 5 supporters and "coming to Racu" beta addicts which is probably a good thing. But, at the same time, the loss of mindshare to Ruby and Python might accelerate.
Wikipedia already jumped the bandwagon: https://en.wikipedia.org/wiki/Raku_(programming_language)
For changes in the language see https://docs.perl6.org/language/5to6-nutshell They are not convincing
Nov 10, 2019 | news.ycombinator.com
makecheck on Oct 7, 2015 [-]
In multiple organizations I have primarily seen Perl used in a very large, complex and established code bases that also make significant use of things like reading/writing Perl data structures.

[Nov 08, 2019] Perl tricks for system administrators by Ruth Holloway Feed

Notable quotes:
"... /home/<department>/<username> ..."
Jul 27, 2016 | opensource.com

Did you know that Perl is a great programming language for system administrators? Perl is platform-independent so you can do things on different operating systems without rewriting your scripts. Scripting in Perl is quick and easy, and its portability makes your scripts amazingly useful. Here are a few examples, just to get your creative juices flowing! Renaming a bunch of files

Suppose you need to rename a whole bunch of files in a directory. In this case, we've got a directory full of .xml files, and we want to rename them all to .html . Easy-peasy!

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

foreach my $file ( glob "*.xml" ) {
my $new = substr ( $file , 0 , - 3 ) . "html" ;
rename $file , $new ;
}

Then just cd to the directory where you need to make the change, and run the script. You could put this in a cron job, if you needed to run it regularly, and it is easily enhanced to accept parameters.

Speaking of accepting parameters, let's take a look at a script that does just that.

Creating a Linux user account

Programming and development

Suppose you need to regularly create Linux user accounts on your system, and the format of the username is first initial/last name, as is common in many businesses. (This is, of course, a good idea, until you get John Smith and Jane Smith working at the same company -- or want John to have two accounts, as he works part-time in two different departments. But humor me, okay?) Each user account needs to be in a group based on their department, and home directories are of the format /home/<department>/<username> . Let's take a look at a script to do that:

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

my $adduser = '/usr/sbin/adduser' ;

use Getopt :: Long qw ( GetOptions ) ;

# If the user calls the script with no parameters,
# give them help!

if ( not @ ARGV ) {
usage () ;
}

# Gather our options; if they specify any undefined option,
# they'll get sent some help!

my %opts ;
GetOptions ( \%opts ,
'fname=s' ,
'lname=s' ,
'dept=s' ,
'run' ,
) or usage () ;

# Let's validate our inputs. All three parameters are
# required, and must be alphabetic.
# You could be clever, and do this with a foreach loop,
# but let's keep it simple for now.

if ( not $opts { fname } or $opts { fname } !~ /^[a-zA-Z]+$/ ) {
usage ( "First name must be alphabetic" ) ;
}
if ( not $opts { lname } or $opts { lname } !~ /^[a-zA-Z]+$/ ) {
usage ( "Last name must be alphabetic" ) ;
}
if ( not $opts { dept } or $opts { dept } !~ /^[a-zA-Z]+$/ ) {
usage ( "Department must be alphabetic" ) ;
}

# Construct the username and home directory

my $username = lc ( substr ( $opts { fname } , 0 , 1 ) . $opts { lname }) ;
my $home = "/home/$opts{dept}/$username" ;

# Show them what we've got ready to go.

print "Name: $opts{fname} $opts{lname} \n " ;
print "Username: $username \n " ;
print "Department: $opts{dept} \n " ;
print "Home directory: $home \n\n " ;

# use qq() here, so that the quotes in the --gecos flag
# get carried into the command!

my $cmd = qq ( $adduser -- home $home -- ingroup $opts { dept } \\
-- gecos "$opts{fname} $opts{lname}" $username ) ;

print "$cmd \n " ;
if ( $opts { run }) {
system $cmd ;
} else {
print "You need to add the --run flag to actually execute \n " ;
}

sub usage {
my ( $msg ) = @_ ;
if ( $msg ) {
print "$msg \n\n " ;
}
print "Usage: $0 --fname FirstName --lname LastName --dept Department --run \n " ;
exit ;
}

As with the previous script, there are opportunities for enhancement, but something like this might be all that you need for this task.

One more, just for fun!

Change copyright text in every Perl source file in a directory tree

Now we're going to try a mass edit. Suppose you've got a directory full of code, and each file has a copyright statement somewhere in it. (Rich Bowen wrote a great article, Copyright statements proliferate inside open source code a couple of years ago that discusses the wisdom of copyright statements in open source code. It is a good read, and I recommend it highly. But again, humor me.) You want to change that text in each and every file in the directory tree. File::Find and File::Slurp are your friends!

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

use File :: Find qw ( find ) ;
use File :: Slurp qw ( read_file write_file ) ;

# If the user gives a directory name, use that. Otherwise,
# use the current directory.

my $dir = $ARGV [ 0 ] || '.' ;

# File::Find::find is kind of dark-arts magic.
# You give it a reference to some code,
# and a directory to hunt in, and it will
# execute that code on every file in the
# directory, and all subdirectories. In this
# case, \&change_file is the reference
# to our code, a subroutine. You could, if
# what you wanted to do was really short,
# include it in a { } block instead. But doing
# it this way is nice and readable.

find ( \&change_file , $dir ) ;

sub change_file {
my $name = $_ ;

# If the file is a directory, symlink, or other
# non-regular file, don't do anything

if ( not - f $name ) {
return ;
}
# If it's not Perl, don't do anything.

if ( substr ( $name , - 3 ) ne ".pl" ) {
return ;
}
print "$name \n " ;

# Gobble up the file, complete with carriage
# returns and everything.
# Be wary of this if you have very large files
# on a system with limited memory!

my $data = read_file ( $name ) ;

# Use a regex to make the change. If the string appears
# more than once, this will change it everywhere!

$data =~ s/Copyright Old/Copyright New/g ;

# Let's not ruin our original files

my $backup = "$name.bak" ;
rename $name , $backup ;
write_file ( $name , $data ) ;

return ;
}

Because of Perl's portability, you could use this script on a Windows system as well as a Linux system -- it Just Works because of the underlying Perl interpreter code. In our create-an-account code above, that one is not portable, but is Linux-specific because it uses Linux commands such as adduser .

In my experience, I've found it useful to have a Git repository of these things somewhere that I can clone on each new system I'm working with. Over time, you'll think of changes to make to the code to enhance the capabilities, or you'll add new scripts, and Git can help you make sure that all your tools and tricks are available on all your systems.

I hope these little scripts have given you some ideas how you can use Perl to make your system administration life a little easier. In addition to these longer scripts, take a look at a fantastic list of Perl one-liners, and links to other Perl magic assembled by Mischa Peterson.

[Oct 22, 2019] Larry Wall Approves Re-Naming Perl 6 To Raku

Oct 22, 2019 | developers.slashdot.org

(github.com) 100 hondo77 notes that Larry Wall has given his approval to the re-naming of Perl 6.

In the "Path to Raku" pull request, Larry Wall indicated his approval, leaving this comment: I am in favor of this change, because it reflects an ancient wisdom :

"No one sews a patch of unshrunk cloth on an old garment, for the patch will pull away from the garment, making the tear worse. Neither do people pour new wine into old wineskins. If they do, the skins will burst; the wine will run out and the wineskins will be ruined. No, they pour new wine into new wineskins, and both are preserved."

"Perl 6 will become Raku, assuming the four people who haven't yet approved the pull request give their okay," reports the Register, adding that Perl 5 will then become simply Perl .

Dozens of comments on that pull request have now already been marked as "outdated," and while a few contributors have made a point of abstaining from the approval process, reviewer Alex Daniel notes that "this pull request will be merged on October 14th if nobody in the list rejects it or requests more changes."

[Oct 13, 2019] How to eliminate a value in the middle of an array in Perl by Gabor Szabo

Gabor Szabo is an expert in Perl who originally wrote Padre Perl Padre http://padre.perlide.org (abandonware since 2013). The last that was available was Ubuntu 10.10.
Notable quotes:
"... This code will set element 3 (the 4th element of the array) to undef , but will NOT change the size of the array: ..."
Oct 13, 2019 | perlmaven.com
In response to an earlier article about undef one of the readers asked me:

How do you eliminate a value in the middle of an array in Perl?

I am not sure if undef and eliminating values from an array are related, though I guess, if we see having a value of undef as being "empty", then I can understand the connection. In general though, setting something to be undef and deleting something is not the same.

Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!

Let's see first how we can set an element of an array to be undef and then how we can delete an element from an array.

We start with the following code:

  1. use Data :: Dumper qw ( Dumper );
  2. my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
  3. print Dumper \@dwarfs ;

When printed using Data::Dumper we get the following output:

$VAR1 = [
          'Doc',
          'Grumpy',
          'Happy',
          'Sleepy',
          'Sneezy',
          'Dopey',
          'Bashful'
        ];
Set an element to undef

Using the return value of the undef() function:

  1. use Data :: Dumper qw ( Dumper );
  2. my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
  3. $dwarfs [ 3 ] = undef ;
  4. print Dumper \@dwarfs ;

This code will set element 3 (the 4th element of the array) to undef , but will NOT change the size of the array:

$VAR1 = [
          'Doc',
          'Grumpy',
          'Happy',
          undef,
          'Sneezy',
          'Dopey',
          'Bashful'
        ];

Using the undef() function directly on an element of an array yields similar results:

  1. use Data :: Dumper qw ( Dumper );
  2. my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
  3. undef $dwarfs [ 3 ];
  4. print Dumper \@dwarfs ;

So for our purposes $dwarfs[3] = undef; and undef $dwarfs[3]; do the same thing. They both can set a value to be undef .

Removing an element from the array using splice

The splice function can totally eliminate the value from the array:

  1. use Data :: Dumper qw ( Dumper );
  2. my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
  3. splice @dwarfs,3,1;
  4. print Dumper \@dwarfs ;
$VAR1 = [
          'Doc',
          'Grumpy',
          'Happy',
          'Sneezy',
          'Dopey',
          'Bashful'
        ];

As you can see, in this case the array became one element shorter as we have removed one of the elements from the middle of the array.

This is how you can delete an element from an array .

[Oct 13, 2019] 7 of the most useful Perl command line options by Gabor Szabo

Oct 13, 2019 | perlmaven.com

-e execute code on the command line

For one-off tasks it can be very useful to be able to run a piece of Perl code without creating a file. The code itself needs to be between quotes. Due to differences between the Unix/Linux shell and the MS Windows Command prompt we need to use different quotes around our code.

On Unix/Linux systsem (including Mac OSX) it is recommended to put our code in single quotes as in the following example:

$ perl -e 'print qq{Hello World\n}'

Hello World

On MS Windows we must use double quotes around our code.

$ perl -e "print qq{Hello World\n}"

Hello World

Internally, it is probably the best to use q and qq instead of single-quote and double-quote, respectively. That might help reduce the confusion caused by the behavior of the shell and command prompt.

-E execute code on the command line with all the latest features enabled

Since version 5.10 of Perl has been released, Perl includes some additional keywords (called features) in the language. For improved backward compatibility these keywords are only enabled if the user explicitly ask for them with use feature ... . For example by writing use feature qw(say); , or by declaring a minimal version of Perl with use 5.010; .

On the command line we can achieve the same by using -E instead of -e . It will turn on all the features of the version of Perl we are currently running.

For me the most important of all these features, at least in one-liners is the say keyword introduced in perl 5.10 . It is just print with a trailing newline added. Nothing fancy, but makes the one-liners even shorter.

The above examples would look like these:

Unix/Linux:

$ perl -E 'say q{Hello World}'

Hello World

MS Windows:

$ perl -E "say q{Hello World}"

Hello World

You can notice the change from qq to q . As we don't need to include a newline \n in our strings we could switch from qq to q .

-n wrap the -e/-E code in a while loop

If we provide the -n command line option it will wrap our code provided using either the -e or the -E options in a while with a diamond operator .

So

perl -n -E 'say if /code/' file.txt

is the same as

while (<>) {
    say if /code/;
}

That will go over all the lines of all the files provided on the command line (in this case it is file.txt) and print out every line that matches the /code/ regex.

-p is like -n with print $_

The -p option is very similar to the -n flag, but it also prints the content of $_ at the end of each iteration.

So we could write:

perl -p -E 's/code/foobar/' file.txt

which would become

while (<>) {
    s/code/foobar/
    print;
}

That will print the result to the screen.

-i for in-place editing

The most common use of -p is together with the -i option that provides "in-place editing". It means that instead of printing to the screen, all the output generated by our one-liner will be written back to the same file it was taken from.

So this one-liner will replace the first appearance of the string "code" by "foobar" in every line of the file "file.txt".

perl -i -p -E 's/code/foobar/' file.txt

[Oct 09, 2019] Static and state variables in Perl

Oct 09, 2019 | perlmaven.com

Prev Next In most of the cases we either want a variable to be accessible only from inside a small scope, inside a function or even inside a loop. These variables get created when we enter the function (or the scope created by a a block) and destroyed when we leave the scope.

In some cases, especially when we don't want to pay attention to our code, we want variables to be global, to be accessible from anywhere in our script and be destroyed only when the script ends. In General having such global variables is not a good practice.

In some cases we want a variable to stay alive between function calls, but still to be private to that function. We want it to retain its value between calls.

Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!

In the C programming language one can designate a variable to be a static variable . This means it gets initialized only once and it sticks around retaining its old value between function calls.

In Perl, the same can be achieved using the state variable which is available starting from version 5.10, but there is a construct that will work in every version of Perl 5. In a way it is even more powerful.

Let's create a counter as an example:

state variable
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub count {
  5. state $counter = 0 ;
  6. $counter ++;
  7. return $counter ;
  8. }
  9. say count ();
  10. say count ();
  11. say count ();
  12. #say $counter;

In this example, instead of using my to declare the internal variable , we used the state keyword.

$counter is initialized to 0 only once, the first time we call counter() . In subsequent calls, the line state $counter = 0; does not get executed and $counter has the same value as it had when we left the function the last time.

Thus the output will be:

1
2
3

If we removed the # from last line, it would generate a Global symbol "$counter" requires explicit package name at ... line ... error when trying to compile the script. This just shows that the variable $counter is not accessible outside the function.

state is executed in the first call

Check out this strange example:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub count {
  5. state $counter = say "world" ;
  6. $counter ++;
  7. return $counter ;
  8. }
  9. say "hello" ;
  10. say count ();
  11. say count ();
  12. say count ();

This will print out

hello
world
2
3
4

showing that the state $counter = say "world"; line only gets executed once. In the first call to count() say , which was also added in version 5.10 , will return 1 upon success.

static variables in the "traditional" way
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my $counter = 0 ;
  6. sub count {
  7. $counter ++;
  8. return $counter ;
  9. }
  10. }
  11. say count ();
  12. say count ();
  13. say count ();

This provides the same result as the above version using state , except that this could work in older versions of perl as well. (Especially if I did not want to use the say keyword, that was also introduced in 5.10.)

This version works because functions declarations are global in perl - so count() is accessible in the main body of the script even though it was declared inside a block. On the other hand the variable $counter is not accessible from the outside world because it was declared inside the block. Lastly, but probably most importantly, it does not get destroyed when we leave the count() function (or when the execution is outside the block), because the existing count() function still references it.

Thus $count is effectively a static variable.

First assignment time
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. say "hi" ;
  5. {
  6. my $counter = say "world" ;
  7. sub count {
  8. $counter ++;
  9. return $counter ;
  10. }
  11. }
  12. say "hello" ;
  13. say count ();
  14. say count ();
  15. say count ();
hi
world
hello
2
3
4

This shows that in this case too, the declaration and the initial assignment my $counter = say "world"; happens only once, but we can also see that the assignment happens before the first call to count() as if the my $counter = say "world"; statement was part of the control flow of the code outside of the block.

Shared static variable

This "traditional" or "home made" static variable has an extra feature. Because it does not belong to the the count() subroutine, but to the block surrounding it, we can declare more than one functions in that block and we can share this static variable between two or even more functions.

For example we could add a reset_counter() function:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my $counter = 0 ;
  6. sub count {
  7. $counter ++;
  8. return $counter ;
  9. }
  10. sub reset_counter {
  11. $counter = 0 ;
  12. }
  13. }
  14. say count ();
  15. say count ();
  16. say count ();
  17. reset_counter ();
  18. say count ();
  19. say count ();
1
2
3
1
2

Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.

Static arrays and hashes

As of now, you cannot use the state declaration in list context. This means you cannot write state @y = (1, 1); . This limitation could be overcome by some extra coding. For example in this implementation of the Fibonacci series, we checked if the array is empty and set the default values:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub fib {
  5. state @y ;
  6. @y = ( 1 , 1 ) if not @y ; # workaround initialization
  7. push @y , $y [ 0 ]+ $y [ 1 ];
  8. return shift @y ;
  9. }
  10. say fib ();
  11. say fib ();
  12. say fib ();
  13. say fib ();
  14. say fib ();

Alternatively we could use the "old-style" static variable with the enclosing block.

Here is the example generating the Fibonacci series:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my @y = ( 1 , 1 );
  6. sub fib {
  7. push @y , $y [ 0 ]+ $y [ 1 ];
  8. return shift @y ;
  9. }
  10. }
  11. say fib ();
  12. say fib ();
  13. say fib ();
  14. say fib ();
  15. say fib ();

[Oct 09, 2019] use vars vs ours

Oct 09, 2019 | perlmaven.com

use vars

The problem is that use strict is complaining that there is a variable $x which is not declared with my and that it does not know about it. So we need a way to tell strict that it is ok. We know about the $x variable and we want to use it, but we want it to be a package variable. We don't want to declare it using my and we don't want to always prefix it with the package name.

With use vars ('$x') we can achieve that:

  1. use strict ;
  2. package VeryLongName ;
  3. use vars ( '$x' );
  4. $x = 23 ;
  5. print "VeryLongName: $x\n" ;

This works, but the documentation of vars tells us that the functionality provided by this pragma has been superseded by "our" declarations .

So how does our work?

our
  1. use strict ;
  2. package VeryLongName ;
  3. our $x = 23 ;
  4. print "VeryLongName: $x\n" ;
Caveat

The our declaration itself is lexically scoped, meaning it is limited by the file or by enclosing curly braces. In the next example we don't have curly braces and thus the declaration our $x = 23; will be intact even after switching namespaces. This can lead to very unpleasant situations. My recommendation is to avoid using our (you almost always need to use my anyway) and to put every package in its own file.

  1. use strict ;
  2. package VeryLongName ;
  3. our $x = 23 ;
  4. print "VeryLongName: $x\n" ; # VeryLongName: 23
  5. package main ;
  6. print "$x\n" ; # 23

[Oct 09, 2019] scope - What is the difference between my and our in Perl - Stack Overflow

Oct 09, 2019 | stackoverflow.com

Asked 10 years, 5 months ago Active 3 years, 1 month ago Viewed 107k times 180 56


Nathan Fellman ,May 10, 2009 at 10:24

I know what my is in Perl. It defines a variable that exists only in the scope of the block in which it is defined. What does our do? How does our differ from my ?

Nathan Fellman ,Nov 20, 2016 at 1:15

Great question: How does our differ from my and what does our do?

In Summary:

Available since Perl 5, my is a way to declare:


On the other hand, our variables are:


Declaring a variable with our allows you to predeclare variables in order to use them under use strict without getting typo warnings or compile-time errors. Since Perl 5.6, it has replaced the obsolete use vars , which was only file-scoped, and not lexically scoped as is our .

For example, the formal, qualified name for variable $x inside package main is $main::x . Declaring our $x allows you to use the bare $x variable without penalty (i.e., without a resulting error), in the scope of the declaration, when the script uses use strict or use strict "vars" . The scope might be one, or two, or more packages, or one small block.

Georg ,Oct 1, 2016 at 6:41

The PerlMonks and PerlDoc links from cartman and Olafur are a great reference - below is my crack at a summary:

my variables are lexically scoped within a single block defined by {} or within the same file if not in {} s. They are not accessible from packages/subroutines defined outside of the same lexical scope / block.

our variables are scoped within a package/file and accessible from any code that use or require that package/file - name conflicts are resolved between packages by prepending the appropriate namespace.

Just to round it out, local variables are "dynamically" scoped, differing from my variables in that they are also accessible from subroutines called within the same block.

Nathan Fellman ,Nov 20, 2015 at 18:46

An example:
use strict;

for (1 .. 2){
    # Both variables are lexically scoped to the block.
    our ($o);  # Belongs to 'main' package.
    my  ($m);  # Does not belong to a package.

    # The variables differ with respect to newness.
    $o ++;
    $m ++;
    print __PACKAGE__, " >> o=$o m=$m\n";  # $m is always 1.

    # The package has changed, but we still have direct,
    # unqualified access to both variables, because the
    # lexical scope has not changed.
    package Fubb;
    print __PACKAGE__, " >> o=$o m=$m\n";
}

# The our() and my() variables differ with respect to privacy.
# We can still access the variable declared with our(), provided
# that we fully qualify its name, but the variable declared
# with my() is unavailable.
print __PACKAGE__, " >> main::o=$main::o\n";  # 2
print __PACKAGE__, " >> main::m=$main::m\n";  # Undefined.

# Attempts to access the variables directly won't compile.
# print __PACKAGE__, " >> o=$o\n";
# print __PACKAGE__, " >> m=$m\n";

# Variables declared with use vars() are like those declared
# with our(): belong to a package; not private; and not new.
# However, their scoping is package-based rather than lexical.
for (1 .. 9){
    use vars qw($uv);
    $uv ++;
}

# Even though we are outside the lexical scope where the
# use vars() variable was declared, we have direct access
# because the package has not changed.
print __PACKAGE__, " >> uv=$uv\n";

# And we can access it from another package.
package Bubb;
print __PACKAGE__, " >> main::uv=$main::uv\n";

daotoad ,May 10, 2009 at 16:37

Coping with Scoping is a good overview of Perl scoping rules. It's old enough that our is not discussed in the body of the text. It is addressed in the Notes section at the end.

The article talks about package variables and dynamic scope and how that differs from lexical variables and lexical scope.

Chas. Owens ,Oct 7, 2013 at 14:02

my is used for local variables, where as our is used for global variables. More reading over Variable Scoping in Perl: the basics .

ruffin ,Feb 10, 2015 at 19:47

It's an old question, but I ever met some pitfalls about lexical declarations in Perl that messed me up, which are also related to this question, so I just add my summary here:

1. definition or declaration?

local $var = 42; 
print "var: $var\n";

The output is var: 42 . However we couldn't tell if local $var = 42; is a definition or declaration. But how about this:

use strict;
use warnings;

local $var = 42;
print "var: $var\n";

The second program will throw an error:

Global symbol "$var" requires explicit package name.

$var is not defined, which means local $var; is just a declaration! Before using local to declare a variable, make sure that it is defined as a global variable previously.

But why this won't fail?

use strict;
use warnings;

local $a = 42;
print "var: $a\n";

The output is: var: 42 .

That's because $a , as well as $b , is a global variable pre-defined in Perl. Remember the sort function?

2. lexical or global?

I was a C programmer before starting using Perl, so the concept of lexical and global variables seems straightforward to me: just corresponds to auto and external variables in C. But there're small differences:

In C, an external variable is a variable defined outside any function block. On the other hand, an automatic variable is a variable defined inside a function block. Like this:

int global;

int main(void) {
    int local;
}

While in Perl, things are subtle:

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

The output is var: 42 , $var is a global variable even it's defined in a function block! Actually in Perl, any variable is declared as global by default.

The lesson is to always add use strict; use warnings; at the beginning of a Perl program, which will force the programmer to declare the lexical variable explicitly, so that we don't get messed up by some mistakes taken for granted.

Ólafur Waage ,May 10, 2009 at 10:25

The perldoc has a good definition of our.

Unlike my, which both allocates storage for a variable and associates a simple name with that storage for use within the current scope, our associates a simple name with a package variable in the current package, for use within the current scope. In other words, our has the same scoping rules as my, but does not necessarily create a variable.

Cosmicnet ,Nov 22, 2014 at 13:57

This is only somewhat related to the question, but I've just discovered a (to me) obscure bit of perl syntax that you can use with "our" (package) variables that you can't use with "my" (local) variables.
#!/usr/bin/perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

Output:

BAR
BAZ

This won't work if you change 'our' to 'my'.

Okuma.Scott ,Sep 6, 2014 at 20:13

print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";

package Changed;

{
        my $test = 10;
        my $test1 = 11;
        print "trying to print local vars from a closed block: $test, $test1\n";
}

&Check_global;

sub Check_global {
        print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package:     $test\n";
print "trying to print local var outside the block $test1\n";

Will Output this:

package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block

In case using "use strict" will get this failure while attempting to run the script:

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

Nathan Fellman ,Nov 5, 2015 at 14:03

Just try to use the following program :
#!/usr/local/bin/perl
use feature ':5.10';
#use warnings;
package a;
{
my $b = 100;
our $a = 10;


print "$a \n";
print "$b \n";
}

package b;

#my $b = 200;
#our $a = 20 ;

print "in package b value of  my b $a::b \n";
print "in package b value of our a  $a::a \n";

Nathan Fellman ,May 16, 2013 at 11:07

#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;

Evgeniy ,Jan 27, 2016 at 4:57

Let us think what an interpreter actually is: it's a piece of code that stores values in memory and lets the instructions in a program that it interprets access those values by their names, which are specified inside these instructions. So, the big job of an interpreter is to shape the rules of how we should use the names in those instructions to access the values that the interpreter stores.

On encountering "my", the interpreter creates a lexical variable: a named value that the interpreter can access only while it executes a block, and only from within that syntactic block. On encountering "our", the interpreter makes a lexical alias of a package variable: it binds a name, which the interpreter is supposed from then on to process as a lexical variable's name, until the block is finished, to the value of the package variable with the same name.

The effect is that you can then pretend that you're using a lexical variable and bypass the rules of 'use strict' on full qualification of package variables. Since the interpreter automatically creates package variables when they are first used, the side effect of using "our" may also be that the interpreter creates a package variable as well. In this case, two things are created: a package variable, which the interpreter can access from everywhere, provided it's properly designated as requested by 'use strict' (prepended with the name of its package and two colons), and its lexical alias.

Sources:

[Oct 09, 2019] Perl Import Package in different Namespace

Oct 09, 2019 | stackoverflow.com

Perl Import Package in different Namespace Ask Question Asked 1 year ago Active 7 months ago Viewed 150 times We're doing things differently. View all 8 job openings! 2


choroba ,Sep 28, 2018 at 22:17

is it possible to import ( use ) a perl module within a different namespace?

Let's say I have a Module A (XS Module with no methods Exported @EXPORT is empty) and I have no way of changing the module.

This Module has a Method A::open

currently I can use that Module in my main program (package main) by calling A::open I would like to have that module inside my package main so that I can directly call open

I tried to manually push every key of %A:: into %main:: however that did not work as expected.

The only way that I know to achieve what I want is by using package A; inside my main program, effectively changing the package of my program from main to A . Im not satisfied with this. I would really like to keep my program inside package main.

Is there any way to achieve this and still keep my program in package main?

Offtopic: Yes I know usually you would not want to import everything into your namespace but this module is used by us extensively and we don't want to type A:: (well the actual module name is way longer which isn't making the situation better)in front of hundreds or thousands of calls

Grinnz ,Oct 1, 2018 at 6:26

This is one of those "impossible" situations, where the clear solution -- to rework that module -- is off limits.

But, you can alias that package's subs names, from its symbol table, to the same names in main . Worse than being rude, this comes with a glitch: it catches all names that that package itself imported in any way. However, since this package is a fixed quantity it stands to reason that you can establish that list (and even hard-code it). It is just this one time, right?

main

use warnings;
use strict;
use feature 'say';

use OffLimits;

GET_SUBS: {
    # The list of names to be excluded
    my $re_exclude = qr/^(?:BEGIN|import)$/;  # ...
    my @subs = grep { !/$re_exclude/ } sort keys %OffLimits::;
    no strict 'refs';
    for my $sub_name (@subs) {
        *{ $sub_name } = \&{ 'OffLimits::' . $sub_name };
    }   
};

my $name = name('name() called from ' . __PACKAGE__);
my $id   = id('id() called from ' . __PACKAGE__);

say "name() returned: $name";
say "id()   returned: $id";

with OffLimits.pm

package OffLimits;    
use warnings;
use strict;

sub name { return "In " .  __PACKAGE__ . ": @_" }
sub id   { return "In " .  __PACKAGE__ . ": @_" }

1;

It prints

name() returned: In OffLimits: name() called from  main
id()   returned: In OffLimits: id() called from  main

You may need that code in a BEGIN block, depending on other details.

Another option is of course to hard-code the subs to be "exported" (in @subs ). Given that the module is in practice immutable this option is reasonable and more reliable.


This can also be wrapped in a module, so that you have the normal, selective, importing.

WrapOffLimits.pm

package WrapOffLimits;
use warnings;
use strict;

use OffLimits;

use Exporter qw(import);

our @sub_names;
our @EXPORT_OK   = @sub_names;
our %EXPORT_TAGS = (all => \@sub_names);

BEGIN { 
    # Or supply a hard-coded list of all module's subs in @sub_names
    my $re_exclude = qr/^(?:BEGIN|import)$/;  # ...
    @sub_names = grep { !/$re_exclude/ } sort keys %OffLimits::;

    no strict 'refs';
    for my $sub_name (@sub_names) {
        *{ $sub_name } = \&{ 'OffLimits::' . $sub_name };
    }   
};
1;

and now in the caller you can import either only some subs

use WrapOffLimits qw(name);

or all

use WrapOffLimits qw(:all);

with otherwise the same main as above for a test.

The module name is hard-coded, which should be OK as this is meant only for that module.


The following is added mostly for completeness.

One can pass the module name to the wrapper by writing one's own import sub, which is what gets used then. The import list can be passed as well, at the expense of an awkward interface of the use statement.

It goes along the lines of

package WrapModule;
use warnings;
use strict;

use OffLimits;

use Exporter qw();  # will need our own import 

our ($mod_name, @sub_names);

our @EXPORT_OK   = @sub_names;
our %EXPORT_TAGS = (all => \@sub_names);

sub import {
    my $mod_name = splice @_, 1, 1;  # remove mod name from @_ for goto

    my $re_exclude = qr/^(?:BEGIN|import)$/;  # etc

    no strict 'refs';
    @sub_names = grep { !/$re_exclude/ } sort keys %{ $mod_name . '::'};    
    for my $sub_name (@sub_names) {    
        *{ $sub_name } = \&{ $mod_name . '::' . $sub_name };
    }   

    push @EXPORT_OK, @sub_names;

    goto &Exporter::import;
}
1;

what can be used as

use WrapModule qw(OffLimits name id);  # or (OffLimits :all)

or, with the list broken-up so to remind the user of the unusual interface

use WrapModule 'OffLimits', qw(name id);

When used with the main above this prints the same output.

The use statement ends up using the import sub defined in the module, which exports symbols by writing to the caller's symbol table. (If no import sub is written then the Exporter 's import method is nicely used, which is how this is normally done.)

This way we are able to unpack the arguments and have the module name supplied at use invocation. With the import list supplied as well now we have to push manually to @EXPORT_OK since this can't be in the BEGIN phase. In the end the sub is replaced by Exporter::import via the (good form of) goto , to complete the job.

Simerax ,Sep 30, 2018 at 10:19

You can forcibly "import" a function into main using glob assignment to alias the subroutine (and you want to do it in BEGIN so it happens at compile time, before calls to that subroutine are parsed later in the file):
use strict;
use warnings;
use Other::Module;

BEGIN { *open = \&Other::Module::open }

However, another problem you might have here is that open is a builtin function, which may cause some problems . You can add use subs 'open'; to indicate that you want to override the built-in function in this case, since you aren't using an actual import function to do so.

Grinnz ,Sep 30, 2018 at 17:33

Here is what I now came up with. Yes this is hacky and yes I also feel like I opened pandoras box with this. However at least a small dummy program ran perfectly fine.

I renamed the module in my code again. In my original post I used the example A::open actually this module does not contain any method/variable reserved by the perl core. This is why I blindly import everything here.

BEGIN {
    # using the caller to determine the parent. Usually this is main but maybe we want it somewhere else in some cases
    my ($parent_package) = caller;

    package A;

    foreach (keys(%A::)) {
        if (defined $$_) {
            eval '*'.$parent_package.'::'.$_.' = \$A::'.$_;
        }
        elsif (%$_) {
            eval '*'.$parent_package.'::'.$_.' = \%A::'.$_;
        }
        elsif (@$_) {
            eval '*'.$parent_package.'::'.$_.' = \@A::'.$_;
        }
        else {
            eval '*'.$parent_package.'::'.$_.' = \&A::'.$_;
        }
    }
}

[Oct 09, 2019] oop - Perl Importing Variables From Calling Module

Oct 09, 2019 | stackoverflow.com

Perl Importing Variables From Calling Module Ask Question Asked 9 years, 1 month ago Active 9 years, 1 month ago Viewed 4k times 0 1


Russell C. ,Aug 31, 2010 at 20:31

I have a Perl module (Module.pm) that initializes a number of variables, some of which I'd like to import ($VAR2, $VAR3) into additional submodules that it might load during execution.

The way I'm currently setting up Module.pm is as follows:

package Module;

use warnings;
use strict;

use vars qw($SUBMODULES $VAR1 $VAR2 $VAR3);

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw($VAR2 $VAR3);

sub new {
    my ($package) = @_;
    my $self = {};
    bless ($self, $package);
    return $self;
}

sub SubModules1 {
    my $self = shift;
    if($SUBMODULES->{'1'}) { return $SUBMODULES->{'1'}; }

    # Load & cache submodule
    require Module::SubModule1;
    $SUBMODULES->{'1'} = Module::SubModule1->new(@_);    
    return $SUBMODULES->{'1'};
}

sub SubModules2 {
    my $self = shift;
    if($SUBMODULES->{'2'}) { return $SUBMODULES->{'2'}; }

    # Load & cache submodule
    require Module::SubModule2;
    $SUBMODULES->{'2'} = Module::SubModule2->new(@_);    
    return $SUBMODULES->{'2'};
}

Each submodule is structured as follows:

package Module::SubModule1;

use warnings;
use strict;
use Carp;

use vars qw();

sub new {
    my ($package) = @_;
    my $self = {};
    bless ($self, $package);
    return $self;
}

I want to be able to import the $VAR2 and $VAR3 variables into each of the submodules without having to reference them as $Module::VAR2 and $Module::VAR3. I noticed that the calling script is able to access both the variables that I have exported in Module.pm in the desired fashion but SubModule1.pm and SubModule2.pm still have to reference the variables as being from Module.pm.

I tried updating each submodule as follows which unfortunately didn't work I was hoping:

package Module::SubModule1;

use warnings;
use strict;
use Carp;

use vars qw($VAR2 $VAR3);

sub new {
    my ($package) = @_;
    my $self = {};
    bless ($self, $package);
    $VAR2 = $Module::VAR2;
    $VAR3 = $Module::VAR3;
    return $self;
}

Please let me know how I can successfully export $VAR2 and $VAR3 from Module.pm into each Submodule. Thanks in advance for your help!

Russell C. ,Aug 31, 2010 at 22:37

In your submodules, are you forgetting to say
use Module;

? Calling use Module from another package (say Module::Submodule9 ) will try to run the Module::import method. Since you don't have that method, it will call the Exporter::import method, and that is where the magic that exports Module 's variables into the Module::Submodule9 namespace will happen.


In your program there is only one Module namespace and only one instance of the (global) variable $Module::VAR2 . Exporting creates aliases to this variable in other namespaces, so the same variable can be accessed in different ways. Try this in a separate script:

package Whatever;
use Module;
use strict;
use vars qw($VAR2);

$Module::VAR2 = 5;
print $Whatever::VAR2;    # should be 5.
$VAR2 = 14;               # same as $Whatever::VAR2 = 14
print $Module::VAR2;      # should be 14

Russell C. ,Aug 31, 2010 at 21:38

Well there is the easy way:

In M.pm:

package M;

use strict;
use warnings;

#our is better than "use vars" for creating package variables
#it creates an alias to $M::foo named $foo in the current lexical scope 
our $foo = 5;

sub inM { print "$foo\n" }

1;

In M/S.pm

package M;

#creates an alias to $M::foo that will last for the entire scope,
#in this case the entire file
our $foo;

package M::S;

use strict;
use warnings;

sub inMS { print "$foo\n" }

1;

In the script:

#!/usr/bin/perl

use strict;
use warnings;

use M;
use M::S;

M::inM();
M::S::inMS();

But I would advise against this. Global variables are not a good practice, and sharing global variables between modules is even worse.

[Oct 09, 2019] Package variables

Oct 09, 2019 | perlmaven.com

These are the oldest type of variables in Perl. They are still used in some cases, even though in most cases you should just use lexical variables.

In old times, if we started to use a variable without declaring it with the my or state keywords, we automatically got a variable in the current namespace. Thus we could write:

  1. $x = 42 ;
  2. print "$x\n" ; # 42

Please note, we don't use strict; in these examples. Even though you should always use strict . We'll fix this in a bit.

The default namespace in every perl script is called "main" and you can always access variables using their full name including the namespace:

  1. $x = 42 ;
  2. print "$x\n" ; # 42
  3. print "$main::x\n" ; # 42

The package keyword is used to switch namespaces:

  1. $x = 42 ;
  2. print "$x\n" ; # 42
  3. print "$main::x\n" ; # 42
  4. package Foo ;
  5. print "Foo: $x\n" ; # Foo:

Please note, once we switched to the "Foo" namespace, the $x name refers to the variable in the Foo namespace. It does not have any value yet.

  1. $x = 42 ;
  2. print "$x\n" ; # 42
  3. print "$main::x\n" ; # 42
  4. package Foo ;
  5. print "Foo: $x\n" ; # Foo:
  6. $x = 23 ;
  7. print "Foo: $x\n" ; # Foo 23;

Do we really have two $x-es? Can we reach the $x in the main namespace while we are in the Foo namespace?

  1. $x = 42 ;
  2. print "$x\n" ; # 42
  3. print "$main::x\n" ; # 42
  4. package Foo ;
  5. print "Foo: $x\n" ; # Foo:
  6. $x = 23 ;
  7. print "Foo: $x\n" ; # Foo 23
  8. print "main: $main::x\n" ; # main: 42
  9. print "Foo: $Foo::x\n" ; # Foo: 23
  10. package main ;
  11. print "main: $main::x\n" ; # main: 42
  12. print "Foo: $Foo::x\n" ; # Foo: 23
  13. print "$x\n" ; # 42

We even switched back to the main namespace (using package main; ) and if you look closely, you can see that while we were already in the main package we could reach to the $x of the Foo package using $Foo::x but if we accessed $x without the full package name, we reach the one in the main namespace.

Every package (or namespace) can hold variables with the same name.

[Oct 08, 2019] Perl constant array

Oct 08, 2019 | stackoverflow.com

Ask Question Asked 6 years, 1 month ago Active 4 years ago Viewed 5k times 4 1


Alec ,Sep 5, 2018 at 8:25

use constant {
    COLUMNS => qw/ TEST1 TEST2 TEST3 /,
}

Can I store an array using the constant package in Perl?

Whenever I go on to try to use the array like my @attr = (COLUMNS); , it does not contain the values.

Сухой27 ,Aug 12, 2013 at 13:37

use constant {
  COLUMNS => [qw/ TEST1 TEST2 TEST3 /],
};

print @{+COLUMNS};

> ,

Or remove the curly braces as the docs show :-
  1 use strict;
  2 use constant COLUMNS => qw/ TEST1 TEST2 TEST3 /;
  3 
  4 my @attr = (COLUMNS);
  5 print @attr;

which gives :-

 % perl test.pl
TEST1TEST2TEST3

Your code actually defines two constants COLUMNS and TEST2 :-

use strict;
use constant { COLUMNS => qw/ TEST1 TEST2 TEST3 /, };

my @attr = (COLUMNS);
print @attr;
print TEST2

and gives :-

% perl test.pl
TEST1TEST3

[Sep 30, 2019] int - perldoc.perl.org

Sep 30, 2019 | perldoc.perl.org

[Sep 24, 2019] warn - perldoc.perl.org

Sep 24, 2019 | perldoc.perl.org

Perl 5 version 30.0 documentation warn Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage

[Sep 21, 2019] Namespaces

Sep 21, 2019 | perl.plover.com

Coping with Scoping

© Copyright 1998 The Perl Journal. Reprinted with permission.

Cet article est également disponible en Français

Questo articolo è disponibile anche in Italiano

Dieser Artikel ist auch in deutscher Übersetzung verfügbar


Just the FAQs: Coping with Scoping

In the Beginning, some time around 1960, every part of your program had access to all the variables in every other part of the program. That turned out to be a problem, so language designers invented local variables, which were visible in only a small part of the program. That way, programmers who used a variable x could be sure that nobody was able to tamper with the contents of x behind their back. They could also be sure that by using x they weren't tampering with someone else's variable by mistake.

Every programming language has a philosophy, and these days most of these philosophies have to do with the way the names of variables are managed. Details of which variables are visible to which parts of the program, and what names mean what, and when, are of prime importance. The details vary from somewhat baroque, in languages like Lisp, to extremely baroque, in languages like C++. Perl unfortunately, falls somewhere towards the rococo end of this scale.

The problem with Perl isn't that it has no clearly-defined system of name management, but rather that it two systems, both working at once. Here's the Big Secret about Perl variables that most people learn too late: Perl has two completely separate, independent sets of variables. One is left over from Perl 4, and the other is new. The two sets of variables are called `package variables' and `lexical variables', and they have nothing to do with each other.

Package variables came first, so we'll talk about them first. Then we'll see some problems with package variables, and how lexical variables were introduced in Perl 5 to avoid these problems. Finally, we'll see how to get Perl to automatically diagnose places where you might not be getting the variable you meant to get, which can find mistakes before they turn into bugs.

Package Variables
        $x = 1

Here, $x is a package variable . There are two important things to know about package variables:

  1. Package variables are what you get if you don't say otherwise.
  2. Package variables are always global.

Global means that package variables are always visible everywhere in every program. After you do $x = 1 , any other part of the program, even some other subroutine defined in some other file, can inspect and modify the value of $x . There's no exception to this; package variables are always global.

Package variables are divided into families, called packages . Every package variable has a name with two parts. The two parts are analogous to the variable's given name and family name. You can call the Vice-President of the United States `Al', if you want, but that's really short for his full name, which is `Al Gore'. Similarly, $x has a full name, which is something like $main::x . The main part is the package qualifier , analogous to the `Gore' part of `Al Gore'. Al Gore and Al Capone are different people even though they're both named `Al'. In the same way, $Gore::Al and $Capone::Al are different variables, and $main::x and $DBI::x are different variables.

You're always allowed to include the package part of the variable's name, and if you do, Perl will know exactly which variable you mean. But for brevity, you usually like to leave the package qualifier off. What happens if you do?

The Current Package

If you just say $x , perl assumes that you mean the variable $x in the current package. What's the current package? It's normally main , but you can change the current package by writing

        package Mypackage;

in your program; from that point on, the current package is Mypackage . The only thing the current package does is affect the interpretation of package variables that you wrote without package names. If the current package is Mypackage , then $x really means $Mypackage::x . If the current package is main , then $x really means $main::x.

If you were writing a module, let's say the MyModule module, you would probably put a line like this at the top of the module file:

        package MyModule;

From there on, all the package variables you used in the module file would be in package MyModule , and you could be pretty sure that those variables wouldn't conflict with the variables in the rest of the program. It wouldn't matter if both you and the author of DBI were to use a variable named $x , because one of those $x es would be $MyModule::x and the other would be $DBI::x .

Remember that package variables are always global. Even if you're not in package DBI, even if you've never heard of package DBI, nothing can stop you from reading from or writing to $DBI::errstr . You don't have to do anything special. $DBI::errstr , like all package variables, is a global variable, and it's available globally; all you have to do is mention its full name to get it. You could even say

        package DBI;
        $errstr = 'Ha ha Tim!';

and that would modify $DBI::errstr .

Package Variable Trivia

There are only three other things to know about package variables, and you might want to skip them on the first reading:

  1. The package with the empty name is the same as main . So $::x is the same as $main::x for any x .
  2. Some variables are always forced to be in package main. For example, if you mention %ENV , Perl assumes that you mean %main::ENV , even if the current package isn't main . If you want %Fred::ENV , you have to say so explicitly, even if the current package is Fred . Other names that are special this way include INC , all the one-punctuation-character names like $_ and $$ , @ARGV , and STDIN , STDOUT , and STDERR .
  3. Package names, but not variable names, can contain :: . You can have a variable named $DBD::Oracle::x. This means the variable x in the package DBD::Oracle ; it has nothing at all to do with the package DBD which is unrelated. Isaac Newton is not related to Olivia Newton-John, and Newton::Isaac is not related to Newton::John::Olivia . Even though it appears that they both begin with Newton , the appearance is deceptive. Newton::John::Olivia is in package Newton::John , not package Newton.

That's all there is to know about package variables.

Package variables are global, which is dangerous, because you can never be sure that someone else isn't tampering with them behind your back. Up through Perl 4, all variables were package variables, which was worrisome. So Perl 5 added new variables that aren't global.

Lexical Variables

Perl's other set of variables are called lexical variables (we'll see why later) or private variables because they're private. They're also sometimes called my variables because they're always declared with my . It's tempting to call them `local variables', because their effect is confined to a small part of the program, but don't do that, because people might think you're talking about Perl's local operator, which we'll see later. When you want a `local variable', think my , not local .

The declaration

        my $x;

creates a new variable, named x , which is totally inaccessible to most parts of the program---anything outside the block where the variable was declared. This block is called the scope of the variable. If the variable wasn't declared in any block, its scope is from the place it was declared to the end of the file.

You can also declare and initialize a my variable by writing something like

        my $x = 119;

You can declare and initialize several at once:

        my ($x, $y, $z, @args) = (5, 23, @_);

Let's see an example of where some private variables will be useful. Consider this subroutine:

        sub print_report {
          @employee_list = @_;
          foreach $employee (@employee_list) {
            $salary = lookup_salary($employee);
            print_partial_report($employee, $salary);
          }
        }

If lookup_salary happens to also use a variable named $employee , that's going to be the same variable as the one used in print_report , and the works might get gummed up. The two programmers responsible for print_report and lookup_salary will have to coordinate to make sure they don't use the same variables. That's a pain. In fact, in even a medium-sized project, it's an intolerable pain.

The solution: Use my variables:

        sub print_report {
          my @employee_list = @_;
          foreach my $employee (@employee_list) {
            my $salary = lookup_salary($employee);
            print_partial_report($employee, $salary);
          }
        }

my @employee_list creates a new array variable which is totally inaccessible outside the print_report function. for my $employee creates a new scalar variable which is totally inaccessible outside the foreach loop, as does my $salary . You don't have to worry that the other functions in the program are tampering with these variables, because they can't; they don't know where to find them, because the names have different meanings outside the scope of the my declarations. These `my variables' are sometimes called `lexical' because their scope depends only on the program text itself, and not on details of execution, such as what gets executed in what order. You can determine the scope by inspecting the source code without knowing what it does. Whenever you see a variable, look for a my declaration higher up in the same block. If you find one, you can be sure that the variable is inaccessible outside that block. If you don't find a declaration in the smallest block, look at the next larger block that contains it, and so on, until you do find one. If there is no my declaration anywhere, then the variable is a package variable.

my variables are not package variables. They're not part of a package, and they don't have package qualifiers. The current package has no effect on the way they're interpreted. Here's an example:

        my $x = 17;

        package A;
        $x = 12;

        package B;
        $x = 20;

        # $x is now 20.
        # $A::x and $B::x are still undefined

The declaration my $x = 17 at the top creates a new lexical variable named x whose scope continues to the end of the file. This new meaning of $x overrides the default meaning, which was that $x meant the package variable $x in the current package.

package A changes the current package, but because $x refers to the lexical variable, not to the package variable, $x=12 doesn't have any effect on $A::x . Similarly, after package B , $x=20 modifies the lexical variable, and not any of the package variables.

At the end of the file, the lexical variable $x holds 20, and the package variables $main::x , $A::x , and $B::x are still undefined. If you had wanted them, you could still have accessed them by using their full names.

The maxim you must remember is:

Package variables are global variables.
For private variables, you must use my .

local and my

Almost everyone already knows that there's a local function that has something to do with local variables. What is it, and how does it related to my ? The answer is simple, but bizarre:

my creates a local variable. local doesn't.

First, here's what local $x really does: It saves the current value of the package variable $x in a safe place, and replaces it with a new value, or with undef if no new value was specified. It also arranges for the old value to be restored when control leaves the current block. The variables that it affects are package variables, which get local values. But package variables are always global, and a local package variable is no exception. To see the difference, try this:

        $lo = 'global';
        $m  = 'global';
        A();

        sub A {
          local $lo = 'AAA';
          my    $m  = 'AAA';
          B();
        }

        sub B {
          print "B ", ($lo eq 'AAA' ? 'can' : 'cannot') ,
                " see the value of lo set by A.\n";

          print "B ", ($m  eq 'AAA' ? 'can' : 'cannot') ,
                " see the value of m  set by A.\n";
        }

This prints

        B can see the value of lo set by A.
        B cannot see the value of m  set by A.

What happened here? The local declaration in A saved a new temporary value, AAA , in the package variable $lo . The old value, global , will be restored when A returns, but before that happens, A calls B . B has no problem accessing the contents of $lo , because $lo is a package variable and package variables are always available everywhere, and so it sees the value AAA set by A .

In contrast, the my declaration created a new, lexically scoped variable named $m , which is only visible inside of function A . Outside of A , $m retains its old meaning: It refers the the package variable $m ; which is still set to global . This is the variable that B sees. It doesn't see the AAA because the variable with that value is a lexical variable, and only exists inside of A .

What Good is local ?

Because local does not actually create local variables, it is not very much use. If, in the example above, B happened to modify the value of $lo , then the value set by A would be overwritten. That is exactly what we don't want to happen. We want each function to have its own variables that are untouchable by the others. This is what my does.

Why have local at all? The answer is 90% history. Early versions of Perl only had global variables. local was very easy to implement, and was added to Perl 4 as a partial solution to the local variable problem. Later, in Perl 5, more work was done, and real local variables were put into the language. But the name local was already taken, so the new feature was invoked with the word my . my was chosen because it suggests privacy, and also because it's very short; the shortness is supposed to encourage you to use it instead of local . my is also faster than local .

When to Use my and When to Use local

Always use my ; never use local .

Wasn't that easy?

Other Properties of my Variables

Every time control reaches a my declaration, Perl creates a new, fresh variable. For example, this code prints x=1 fifty times:

        for (1 .. 50) {
          my $x;
          $x++;
          print "x=$x\n";
        }

You get a new $x , initialized to undef , every time through the loop.

If the declaration were outside the loop, control would only pass by it once, so there would only be one variable:

        { my $x;
          for (1 .. 50) {
            $x++;
            print "x=$x\n";
          }     
        }

This prints x=1 , x=2 , x=3 , ... x=50 .

You can use this to play a useful trick. Suppose you have a function that needs to remember a value from one call to the next. For example, consider a random number generator. A typical random number generator (like Perl's rand function) has a seed in it. The seed is just a number. When you ask the random number generator for a random number, the function performs some arithmetic operation that scrambles the seed, and it returns the result. It also saves the result and uses it as the seed for the next time it is called.

Here's typical code: (I stole it from the ANSI C standard, but it behaves poorly, so don't use it for anything important.)

        $seed = 1;
        sub my_rand {
          $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;
          return $seed;
        }

And typical output:

        16838
        14666
        10953
        11665
        7451
        26316
        27974
        27550

There's a problem here, which is that $seed is a global variable, and that means we have to worry that someone might inadvertently tamper with it. Or they might tamper with it on purpose, which could affect the rest of the program. What if the function were used in a gambling program, and someone tampered with the random number generator?

But we can't declare $seed as a my variable in the function:

        sub my_rand {
          my $seed;
          $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;
          return $seed;
        }

If we did, it would be initialized to undef every time we called my_rand . We need it to retain its value between calls to my_rand .

Here's the solution:

        { my $seed = 1;
          sub my_rand {
            $seed = int(($seed * 1103515245 + 12345) / 65536) % 32768;
            return $seed;
          }
        }

The declaration is outside the function, so it only happens once, at the time the program is compiled, not every time the function is called. But it's a my variable, and it's in a block, so it's only accessible to code inside the block. my_rand is the only other thing in the block, so the $seed variable is only accessible to the my_rand function.

$seed here is sometimes called a `static' variable, because it stays the same in between calls to the function. (And because there's a similar feature in the C language that is activated by the static keyword.)

my Variable Trivia
  1. You can't declare a variable my if its name is a punctuation character, like $_ , @_ , or $$ . You can't declare the backreference variables $1 , $2 , ... as my . The authors of my thought that that would be too confusing.
  2. Obviously, you can't say my $DBI::errstr , because that's contradictory---it says that the package variable $DBI::errstr is now a lexical variable. But you can say local $DBI::errstr ; it saves the current value of $DBI::errstr and arranges for it to be restored at the end of the block.
  3. New in Perl 5.004, you can write
            foreach my $i (@list) {
    

    instead, to confine the $i to the scope of the loop instead. Similarly,

            for (my $i=0; $i<100; $i++) {
    

    confines the scope of $i to the for loop.

Declarations

If you're writing a function, and you want it to have private variables, you need to declare the variables with my . What happens if you forget?

        sub function {
          $x = 42;        # Oops, should have been my $x = 42.
        }

In this case, your function modifies the global package variable $x . If you were using that variable for something else, it could be a disaster for your program.

Recent versions of Perl have an optional protection against this that you can enable if you want. If you put

        use strict 'vars';

at the top of your program, Perl will require that package variables have an explicit package qualifier. The $x in $x=42 has no such qualifier, so the program won't even compile; instead, the compiler will abort and deliver this error message:

        Global symbol "$x" requires explicit package name at ...

If you wanted $x to be a private my variable, you can go back and add the my . If you really wanted to use the global package variable, you could go back and change it to

        $main::x = 42;

or whatever would be appropriate.

Just saying use strict turns on strict vars , and several other checks besides. See perldoc strict for more details.

Now suppose you're writing the Algorithms::KnuthBendix modules, and you want the protections of strict vars But you're afraid that you won't be able to finish the module because your fingers are starting to fall off from typing $Algorithms::KnuthBendix::Error all the time.

You can save your fingers and tell strict vars to make an exception:

        package Algorithms::KnuthBendix;
        use vars '$Error';

This exempts the package variable $Algorithms::KnuthBendix::Error from causing a strict vars failure if you refer to it by its short name, $Error .

You can also turn strict vars off for the scope of one block by writing

        { no strict 'vars';

          # strict vars is off for the rest of the block.

        }
Summary

Package variables are always global. They have a name and a package qualifier. You can omit the package qualifier, in which case Perl uses a default, which you can set with the package declaration. For private variables, use my . Don't use local ; it's obsolete.

You should avoid using global variables because it can be hard to be sure that no two parts of the program are using one another's variables by mistake.

To avoid using global variables by accident, add use strict 'vars' to your program. It checks to make sure that all variables are either declared private, are explicitly qualified with package qualifiers, or are explicitly declared with use vars .


Glossary
Notes
  1. The tech editors complained about my maxim `Never use local .' But 97% of the time, the maxim is exactly right. local has a few uses, but only a few, and they don't come up too often, so I left them out, because the whole point of a tutorial article is to present 97% of the utility in 50% of the space.

    I was still afraid I'd get a lot of tiresome email from people saying ``You forgot to mention that local can be used for such-and-so, you know.'' So in the colophon at the end of the article, I threatened to deliver Seven Useful Uses for local in three months. I mostly said it to get people off my back about local . But it turned out that I did write it, and it was published some time later.

    The Seven Useful Uses of local is now available on the web site. It appeared in The Perl Journal issue #14.

  2. Here's another potentially interesting matter that I left out for space and clarity. I got email from Robert Watkins with a program he was writing that didn't work. The essence of the bug looked like this:
            my $x;
    
            for $x (1..5) {
              s();
            }
    
            sub s { print "$x, " }
    

    Robert wanted this to print 1, 2, 3, 4, 5, but it did not. Instead, it printed , , , , , . Where did the values of $x go?

    The deal here is that normally, when you write something like this:

                        for $x (...) { }
    

    Perl wants to confine the value of the index variable to inside the loop. If $x is a package variable, it pretends that you wrote this instead:

            { local $x; for $x (...) { } }
    

    But if $x is a lexical variable, it pretends you wrote this instead, instead:

            { my $x;    for $x (...) { } }
    

    This means that the loop index variable won't get propagated to subroutines, even if they're in the scope of the original declaration.

    I probably shouldn't have gone on at such length, because the perlsyn manual page describes it pretty well:

    ...the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my , it uses that variable instead of the global one, but it's still localized to the loop. (Note that a lexically scoped variable can cause problems if you have subroutine or format declarations within the loop which refer to it.)

    In my opinion, lexically scoping the index variable was probably a mistake. If you had wanted that, you would have written for my $x ... in the first place. What I would have liked it to do was to localize the lexical variable: It could save the value of the lexical variable before the loop, and restore it again afterwards. But there may be technical reasons why that couldn't be done, because this doesn't work either:

       my $m;
            { local $m = 12;
              ...
            }
    

    The local fails with this error message:

       Can't localize lexical variable $m...
    

    There's been talk on P5P about making this work, but I gather it's not trivial.

  3. Added 2000-01-05: Perl 5.6.0 introduced a new our(...) declaration. Its syntax is the same as for my() , and it is a replacement for use vars .

    Without getting into the details, our() is just like use vars ; its only effect is to declare variables so that they are exempt from the strict 'vars' checking. It has two possible advantages over use vars , however: Its syntax is less weird, and its effect is lexical. That is, the exception that it creates to the strict checking continues only to the end of the current block:

            use strict 'vars';
            {
              our($x);
              $x = 1;   # Use of global variable $x here is OK
            }
            $x = 2;     # Use of $x here is a compile-time error as usual
    

    So whereas use vars '$x' declares that it is OK to use the global variable $x everywhere, our($x) allows you to say that global $x should be permitted only in certain parts of your program, and should still be flagged as an error if you accidentally use it elsewhere.

  4. Added 2000-01-05: Here's a little wart that takes people by surprise. Consider the following program:
            use strict 'vars';
            my @lines = <>;
            my @sorted = sort backwards @lines;
            print @sorted;
    
            sub backwards { $b cmp $a }
    

    Here we have not declared $a or $b , so they are global variables. In fact, they have to be global, because the sort operator must to be able to set them up for the backwards function. Why doesn't strict produce a failure?

    The variables $a and $b are exempted from strict vars checking, for exactly this reason.

[Sep 21, 2019] Writing PERL Modules - Tutorialspoint

Sep 21, 2019 | www.tutorialspoint.com

What are Packages?

The Package Statement
$i = 1; print "$i\n"; # Prints "1"
package foo;
$i = 2; print "$i\n"; # Prints "2"
package main;
print "$i\n"; # Prints "1"
$PACKAGE_NAME::VARIABLE_NAME

For Example:
$i = 1; print "$i\n"; # Prints "1"
package foo;
$i = 2; print "$i\n"; # Prints "2"
package main;
print "$i\n"; # Prints "1"

print "$foo::i\n"; # Prints "2"
BEGIN and END Blocks

You may define any number of code blocks named BEGIN and END which act as constructors and destructors respectively.

BEGIN { ... }
END { ... }
BEGIN { ... }
END { ... }
What are Perl Modules?

A Perl module is a reusable package defined in a library file whose name is the same as the name of the package (with a .pm on the end).

A Perl module file called "Foo.pm" might contain statements like this.

#!/usr/bin/perl

package Foo;
sub bar { 
   print "Hello $_[0]\n" 
}

sub blat { 
   print "World $_[0]\n" 
}
1;

Few noteable points about modules

The Require Function

A module can be loaded by calling the require function

#!/usr/bin/perl

require Foo;

Foo::bar( "a" );
Foo::blat( "b" );

Notice above that the subroutine names must be fully qualified (because they are isolated in their own package)

It would be nice to enable the functions bar and blat to be imported into our own namespace so we wouldn't have to use the Foo:: qualifier.

The Use Function

A module can be loaded by calling the use function

#!/usr/bin/perl

use Foo;

bar( "a" );
blat( "b" );

Notice that we didn't have to fully qualify the package's function names?

The use function will export a list of symbols from a module given a few added statements inside a module

require Exporter;
@ISA = qw(Exporter);

Then, provide a list of symbols (scalars, lists, hashes, subroutines, etc) by filling the list variable named @EXPORT : For Example

package Module;

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(bar blat);

sub bar { print "Hello $_[0]\n" }
sub blat { print "World $_[0]\n" }
sub splat { print "Not $_[0]\n" }  # Not exported!

1;
Create the Perl Module Tree

When you are ready to ship your PERL module then there is standard way of creating a Perl Module Tree. This is done using h2xs utility. This utility comes alongwith PERL. Here is the syntax to use h2xs

$h2xs -AX -n  Module Name

# For example, if your module is available in Person.pm file
$h2xs -AX -n Person

This will produce following result
Writing Person/lib/Person.pm
Writing Person/Makefile.PL
Writing Person/README
Writing Person/t/Person.t
Writing Person/Changes
Writing Person/MANIFEST

Here is the descritpion of these options

So above command creates the following structure inside Person directory. Actual result is shown above.

So finally you tar this directory structure into a file Person.tar and you can ship it. You would have to update README file with the proper instructions. You can provide some test examples files in t directory.

Installing Perl Module

Installing a Perl Module is very easy. Use the following sequence to install any Perl Module.

perl Makefile.PL
make
make install

The Perl interpreter has a list of directories in which it searches for modules (global array @INC)

[Sep 21, 2019] How Did Perl Lose Ground to Bash?

Notable quotes:
"... It baffles me the most because the common objection to Perl is legibility. Even if you assume that the objection is made from ignorance - i.e. not even having looked at some Perl to gauge its legibility - the nonsense you see in a complex bash script is orders of magnitude worse! ..."
"... Maybe it's not reassuring to hear that, but I took an interest in Perl precisely because it's seen as an underdog and "dead" despite having experienced users and a lot of code, kind of like TCL, Prolog, or Ada. ..."
"... There's a long history of bad code written by mediocre developers who became the only one who could maintain the codebase until they no longer worked for the organization. The next poor sap to go in found a mess of a codebase and did their best to not break it further. After a few iterations, the whole thing is ready for /dev/null and Perl gets the blame. ..."
"... All in all, Perl is still my first go-to language, but there are definitely some things I wish it did better. ..."
"... The Perl leadership Osborned itself with Perl6. 20/20 hindsight says the new project should have been given a different name at conception, that way all the "watch this space -- under construction" signage wouldn't have steered people away from perfectly usable Perl5. Again, IMO. ..."
"... I don't observe the premise at all though. Is bash really gaining ground over anything recently? ..."
"... Python again is loved, because "taught by rote" idiots. Now you can give them pretty little packages. And it's no wonder they can do little better than be glorified system admins (which id rather have a real sys admin, since he's likely to understand Perl) ..."
"... Making a new language means lots of new training. Lots of profit in this. Nobody profits from writing new books on old languages. Lots of profit in general from supporting a new language. In the end, owning the language gets you profits. ..."
"... And I still don't get why tab for blocks python is even remotely more readable than Perl. ..."
"... If anything, JavaScript is pretty dang godly at what it does, I understand why that's popular. But I don't get python one bit, except to employ millions of entry level minions who can't think on their own. ..."
"... "Every teacher I know has students using it. We do it because it's an easy language, there's only one way to do it, and with whitespace as syntax it's easy to grade. We don't teach it because it is some powerful or exceptional language. " ..."
Sep 21, 2019 | www.reddit.com

How Did Perl Lose Ground to Bash?

Setting aside Perl vs. Python for the moment, how did Perl lose ground to Bash? It used to be that Bash scripts often got replaced by Perl scripts because Perl was more powerful. Even with very modern versions of Bash, Perl is much more powerful.

The Linux Standards Base (LSB) has helped ensure that certain tools are in predictable locations. Bash has gotten a bit more powerful since the release of 4.x, sure. Arrays, handicapped to 2-D arrays, have improved somewhat. There is a native regex engine in Bash 3.x, which admit is a big deal. There is also support for hash maps.

This is all good stuff for Bash. But, none of this is sufficient to explain why Perl isn't the thing you learn after Bash, or, after Bash and Python; take your pick. Thoughts?

28 comments 75% Upvoted What are your thoughts? Log in or Sign up log in sign up Sort by

oldmanwillow21 9 points · 9 days ago

Because Perl has suffered immensely in the popularity arena and is now viewed as undesirable. It's not that Bash is seen as an adequate replacement for Perl, that's where Python has landed.

emilper 8 points · 8 days ago

How did Perl5 lose ground to anything else?

Thusly

- "thou must use Moose for everything" -> "Perl is too slow" -> rewrite in Python because the architect loves Python -> Python is even slower -> architect shunned by the team and everything new written in Go, nobody dares to complain about speed now because the budget people don't trust them -> Perl is slow

- "globals are bad, singletons are good" -> spaghetti -> Perl is unreadable

- "lets use every single item from the gang of four book" -> insanity -> Perl is bad

- "we must be more OOP" -> everything is a faux object with everything else as attributes -> maintenance team quits and they all take PHP jobs, at least the PHP people know their place in the order of things and do less hype-driven-development -> Perl is not OOP enough

- "CGI is bad" -> app needs 6.54GB of RAM for one worker -> customer refuses to pay for more RAM, fires the team, picks a PHP team to do the next version -> PHP team laughs all the way to the bank, chanting "CGI is king"

recrof 2 points · 8 days ago

"CGI is bad" is real. PSGI or FCGI is much faster for web services, and if there are memory leaks, it's always possible to debug & fix them.

Grinnz 6 points · 8 days ago

CGI is fine, when it's all you need. There are many different use cases out there. Just don't use CGI.pm .

emilper 2 points · 7 days ago

memory leaks

memory leaks ... do huge monoliths count as "memory leaks" ?

Altreus 7 points · 8 days ago

It baffles me the most because the common objection to Perl is legibility. Even if you assume that the objection is made from ignorance - i.e. not even having looked at some Perl to gauge its legibility - the nonsense you see in a complex bash script is orders of magnitude worse!

Not to mention its total lack of common language features like first-class data and... Like, a compiler...

I no longer write bash scripts because it takes about 5 lines to become unmaintainable.

crashorbit 5 points · 9 days ago

Every language that reaches functional equity with Perl is perceived as better than it. Mostly because hey, at least it's not Perl.

oldmanwillow21 15 points · 9 days ago · edited 9 days ago

Jumbled mess of thoughts surely to follow.

When I discuss projects with peers and mention that I chose to develop in Perl, the responses range from passive bemusement, to scorn, to ridicule. The assumption is usually that I'm using a dead language that's crippled in functionality and uses syntax that will surely make everyone's eyes bleed to read. This is the culture everywhere from the casual hackers to the C-suite.

I've proven at work that I can write nontrivial software using Perl. I'm still asked to use Python or Go (edit: or node, ugh) for any project that'll have contributors from other teams, or to containerize apps using Docker to remove the need for Perl knowledge for end-users (no CPAN, carton, etc.). But I'll take what I can get, and now the attitude has gone from "get with the times" or "that's cute", to "ok but I don't expect everyone else to know it".

Perl has got a lot to offer, and I vastly enjoy using it over other languages I work with. I know that all the impassioned figures in the Perl community love it just the same, but the community's got some major fragmentation going on. I understand that everyone's got ideas about the future of the language, but is this really the best time to pull the community apart? I feel like if everyone was able to let go of their ego and put their heads together to bring us to a point of stability, even a place where we're not laughed at for professing our support for the language, it would be a major step in the right direction. I think we're heading to the bottom fast, otherwise.

In that spirit of togetherness, I think the language, particularly the community, needs to be made more accessible to newcomers. Not accessible to one Perl offshoot, but accessible to Perl. It needs to be decided what Perl means in today's day and age. What can it do? Why would I want to use it over another shiny language? What are the definitive places I can go to learn more? Who else will be there? How do I contribute and grow as a Perl developer? There need to be people talking about Perl in places that aren't necessarily hubs for other Perl enthusiasts. It needs to be something business decision-makers can look at and feel confident in using.

I really hope something changes. I'd be pretty sad if I had to spend the rest of my career writing whatever the trendy language of the day is. These are just observations from someone that likes writing Perl and has been watching from the sidelines.

PhloxPaniculata 2 points · 7 days ago

Maybe it's not reassuring to hear that, but I took an interest in Perl precisely because it's seen as an underdog and "dead" despite having experienced users and a lot of code, kind of like TCL, Prolog, or Ada.

Being able to read Modern Perl for free also helped a lot. I'm still lacking experience in Perl and I've yet to write anything of importance in it because I don't see an area in which it's clearly better than anything else, either because of the language, a package, or a framework, and I don't do a lot of text-munging anymore (I'm also a fan of awk so for small tasks it has the priority).

codon011 1 point · 9 days ago

Don't call it Perl. Unfortunately. Also IME multitasking in Perl5 (or the lack thereof and/or severe issues with) has been a detriment to it's standing in a "multithread all the things" world.

crashorbit 4 points · 8 days ago

So often I see people drag themselves down that "thread my app" path. Eventually realize that they are implementing a whole multi-processing operating system inside their app rather than taking advantage of the perfectly good one they are running on.

There are several perfectly good ways to do concurrency, multitasking, async IO and so on in perl. Many work well in the single node case and in the multi-node case. Anyone who tells you that multitasking systems are easy because of some implementation language choice has not made it through the whole Dunning Kruger cycle yet.

codon011 2 points · 8 days ago

Multithreading is never easy. The processors will always manage to do things in a "wrong" order unless you are very careful with your gatekeeping. However, other languages/frameworks have paradigms that make it seem easier such that those race conditions show up much later in your product lifecycle.

codon011 3 points · 9 days ago

There's a long history of bad code written by mediocre developers who became the only one who could maintain the codebase until they no longer worked for the organization. The next poor sap to go in found a mess of a codebase and did their best to not break it further. After a few iterations, the whole thing is ready for /dev/null and Perl gets the blame.

Bash has limitations, but that (usually) means fewer ways to mess it up. There's less domain knowledge to learn, (afaik) no CPAN equivalent, and fewer issues with things like "I need to upgrade this but I can't because this other thing uses this older version which is incompatible with the newer version so now we have to maintain two versions of the library and/or interpreter."

All in all, Perl is still my first go-to language, but there are definitely some things I wish it did better.

crb3 3 points · 9 days ago · edited 9 days ago

*[e:] Consider, not just core here, but CPAN pull-in as well. I had one project clobbered on a smaller-memory machine when I tried to set up a pure-Perl scp transfer -- there wasn't room enough for the full file to transfer if it was larger than about 50k, what with all the CPAN. Shelling to commandline scp worked just fine.

beermad 2 points · 8 days ago

To be fair, wrapping a Perl script around something that's (if I read your comment right) just running SCP is adding a pointless extra layer of complexity anyway.

It's a matter of using the best tool for each particular job, not just sticking with one. My own ~/bin directory has a big mix of Perl and pure shell, depending on the complexity of the job to be done.

crb3 2 points · 8 days ago · edited 7 days ago

Agreed; I brought that example up to illustrate the bulk issue. In it, I was feeling my way, not sure how much finagling I might have to do for the task (backdoor-passing legitimate sparse but possibly quite bulky email from one server to another), which is why I initially went for the pure-Perl approach, so I'd have the mechanics exposed for any needed hackery. The experience taught me to get by more on shelling to precompiled tooling where appropriate... and a healthy respect for CPAN pull-in, [e:] the way that this module depends on that module so it gets pulled in along with its dependencies in turn, and the pileup grows in memory. There was a time or two here and there where I only needed a teeny bit of what a module does, so I went in and studied the code, then implemented it internally as a function without the object's generalities and bulk. The caution learned on ancient x86 boxes now seems appropriate on ARM boards like rPi; what goes around comes around.

minimim 1 point · 4 days ago

wouldn't have steered people away from perfectly usable Perl5

Perl5 development was completely stalled at the time. Perl6 brought not only new blood into it's own effort, it reinvigorated Perl5 in the process.

It's completely backwards to suggest Perl 5 was fine until perl6 came along. It was almost dormant and became a lively language after Perl 6 was announced.

perlancar 2 points · 8 days ago

I don't observe the premise at all though. Is bash really gaining ground over anything recently? l

linearblade 3 points · 8 days ago

Perl is better than pretty much everything g out there at what it does.

But keep in mind,

They say C sharp is loved by everyone, when in reality it's Microsoft pushing their narrative and the army of "learn by rote" engineers In developing countries

Python again is loved, because "taught by rote" idiots. Now you can give them pretty little packages. And it's no wonder they can do little better than be glorified system admins (which id rather have a real sys admin, since he's likely to understand Perl)

Making a new language means lots of new training. Lots of profit in this. Nobody profits from writing new books on old languages. Lots of profit in general from supporting a new language. In the end, owning the language gets you profits.

And I still don't get why tab for blocks python is even remotely more readable than Perl.

If anything, JavaScript is pretty dang godly at what it does, I understand why that's popular. But I don't get python one bit, except to employ millions of entry level minions who can't think on their own.

duo-rotae 6 points · 8 days ago

I know a comp sci professor. I asked why he thought Python was so popular.

"Every teacher I know has students using it. We do it because it's an easy language, there's only one way to do it, and with whitespace as syntax it's easy to grade. We don't teach it because it is some powerful or exceptional language. "

Then he said if he really needs to get something done, it's Perl or C.

linearblade 2 points · 8 days ago

Yep that's pretty much my opinion from using it.

techsnapp 1 point · 2 days ago

So is per harder than python because the lack of everyone else using it?

duo-rotae 1 point · 2 days ago

Perl has a steeper and longer learning with it. curve than Python, and there is more than one way to do anything. And there quite a few that continue coding

[Sep 19, 2019] Min and max functions in Perl by Tim

Feb 01, 2012 | timmurphy.org

Posted: 1st February 2012 by Tim in Perl

Tags: list , math , max , min , Perl , script 3

Min and max functions are available in perl, but you need to load them first. To do this, add

use List::Util qw[min max];

to the top of the script. These functions take a list of numbers and return the min/max of that list. The list can have 2 numbers or 100 – it doesn't matter:

use List::Util qw[min max];

print min(1,3) . "\n";
print max(1,2,3,4,5) . "\n";
print min(1) . "\n";

[Sep 19, 2019] Luke's Thought Dump Cute Perl Gem to Get the Minimum-Maximum Value

Notable quotes:
"... the comparison operators return 1 or 0 for true and false, respectively, which are then used by this code to index the array ref. ..."
Sep 19, 2019 | lukesthoughtdump.blogspot.com

Sunday, August 2, 2009 Cute Perl Gem to Get the Minimum/Maximum Value Saw this little nugget on #perl@irc.perl.org the other night. It determines the minimum of two values:

[$b, $a]->[$a <= $b]
It takes advantage of the fact that Perl doesn't have a Boolean return type for true or false, so the comparison operators return 1 or 0 for true and false, respectively, which are then used by this code to index the array ref.

To get the maximum of the two values, just flip the operator to >= Posted by Luke at

Labels: hacks , perl

[Sep 19, 2019] List::MoreUtils's minmax is more efficient when you need both the min and the max (because it does fewer comparisons).

Notable quotes:
"... List::MoreUtils's minmax is more efficient when you need both the min and the max (because it does fewer comparisons). ..."
Sep 19, 2019 | stackoverflow.com

List::Util's min and max are fine,

use List::Util qw( min max );
my $min = min @numbers;
my $max = max @numbers;

But List::MoreUtils's minmax is more efficient when you need both the min and the max (because it does fewer comparisons).

use List::MoreUtils qw( minmax );
my ($min, $max) = minmax @numbers;

List::Util is part of core, but List::MoreUtils isn't.

--ikegami

[Sep 16, 2019] Perl For Dummies Cheat Sheet

Sep 16, 2019 | www.dummies.com

From Perl For Dummies, 4th Edition

By Paul Hoffman

Perl enables you to write powerful programs right from the start, whether you're a programming novice or expert. Perl offers the standard programming tools -- comparison operators, pattern-matching quantifiers, list functions -- and has shortcuts for inputting character ranges. Perl also offers file tests so you can find what you want fast.

The Most Useful File Tests in Perl

Programming with Perl is fairly straightforward, which runs to the letters you use for file tests. For example, r tests whether a file can be r ead, and T looks for a t ext file. Here are most useful file tests in Perl:

Test Description
-e File exists.
-r File can be read.
-w File can be written to.
-z File is exactly zero bytes long.
-d Named item is a directory, not a file.
-T File is a text file. (The first chunk of a file is examined,
and it's a text file if fewer than 30 percent or so of the
characters are nonprintable.)
-B File is a binary file. (This is the exact opposite of the -T
test -- it's a binary file if more than 30 percent or so
of the characters are nonprintable.)
-s Size of the file in bytes.
-C Creation age of file.
-A Access age of file.
-M Modification age of file.
Special Characters in Perl

Like any programming language, Perl uses special commands for special characters, such as backspaces or vertical tabs. So, if you need to program in a bell or a beep or just a carriage return, check the following table for the character that will produce it:

Character Meaning
n Newline
r Carriage return
t Tab character
f Formfeed character
b Backspace character
v Vertical tab
a Bell or beep
e Escape character
Perl True-False Comparison Operators

When you're programming with Perl -- or any other language -- you use comparison operators all the time. The following table shows the common comparisons for Perl in both math and string form:

Comparison Math String
Equal to == eq
Not equal to != ne
Less than < lt
Greater than > gt
Less than or equal to <= le
Greater than or equal to >= ge
Common List Functions in Perl

Perl was originally designed to help process reports more easily. Reports often contain lists, and you may want to use Perl to perform certain functions within a list. The following table shows you common list functions, their splice equivalents, and explains what the function does:

Function splice Equivalent What It Does
push (@r, @s) splice(@r, $#r+1,0, @s) Adds to the right of the list
pop (@r) splice(@r, $#r, 1) Removes from the right of the list
shift (@r) splice(@r, 0, 1) Removes from the left of the list
unshift (@r, @s) splice(@r, 0, 0,@s) Adds to the left of the list
Shortcuts for Character Ranges in Perl

You're programming along in Perl and want to use a code shortcut to represent anything from a number to a non-number to any letter or number. You're in luck, because the following table gives you the code, shows you what it's a shortcut for, and describes it.

Code Replaces Description
d [0..9] Any digit
w [a-zA-Z_0-9] Any alphanumeric character
s [ tnrf] A whitespace character
D ^[0..9] Any non-digit
W ^[a-zA-Z_0-9] Any non-alphanumeric character
S ^[ tnrf] A non-whitespace character
Perl Pattern-Matching Quantifiers

Perl enables you to use common symbols to instruct the program you're writing to match data once, never, or up to a certain number of times. The following table shows you which symbol to use to get the match you want:

Symbol Meaning
+ Match 1 or more times
* Match 0 or more times
? Match 0 or 1 time
{n} Match exactly n times
{n,} Match at least n times
{n,m} Match at least n, but not more than m, times (these values must
be less than 65,536)

[Sep 16, 2019] How can I capture multiple matches from the same Perl regex - Stack Overflow

Sep 16, 2019 | stackoverflow.com

How can I capture multiple matches from the same Perl regex? Ask Question Asked 9 years, 4 months ago Active 7 years, 4 months ago Viewed 35k times 24 1


brian d foy ,May 22, 2010 at 15:42

I'm trying to parse a single string and get multiple chunks of data out from the same string with the same regex conditions. I'm parsing a single HTML doc that is static (For an undisclosed reason, I can't use an HTML parser to do the job.) I have an expression that looks like:
$string =~ /\<img\ssrc\="(.*)"/;

and I want to get the value of $1. However, in the one string, there are many img tags like this, so I need something like an array returned (@1?) is this possible?

VolatileRig ,Jan 14, 2014 at 19:41

As Jim's answer, use the /g modifier (in list context or in a loop).

But beware of greediness, you dont want the .* to match more than necessary (and dont escape < = , they are not special).

while($string =~ /<img\s+src="(.*?)"/g ) {
  ...
}

Robert Wohlfarth ,May 21, 2010 at 18:44

@list = ($string =~ m/\<img\ssrc\="(.*)"/g);

The g modifier matches all occurences in the string. List context returns all of the matches. See the m// operator in perlop .

dalton ,May 21, 2010 at 18:42

You just need the global modifier /g at the end of the match. Then loop through until there are no matches remaining
my @matches;
while ($string =~ /\<img\ssrc\="(.*)"/g) {
        push(@matches, $1);
}

VolatileRig ,May 24, 2010 at 16:37

Use the /g modifier and list context on the left, as in
@result = $string =~ /\<img\ssrc\="(.*)"/g;

[Sep 16, 2019] https://www.dummies.com/programming/perl/avoiding-common-oversights-in-perl/

Sep 16, 2019 | www.dummies.com

Avoiding Common Oversights in Perl

Related Book

Perl For Dummies, 4th Edition

By Paul Hoffman

Entering a typo or two during the course of writing a Perl program is not uncommon. But when you attempt to run a program containing a text-entry slip-up, Perl usually becomes confused and tells you so by reporting an error. The natural reaction for most people, even those with years of programming experience, is to get worried or angry or both when an error message pops up.

Don't panic. Take a deep breath. Take another slow, deep breath. Seriously, you can't get to the root of the problem if you're all tense and bothered. No matter how many years you program, you always end up finding some errors in the code you're written.

So, now that you are (hopefully!) a bit calmer, you can start to appreciate the fact that Perl has more helpful error messages than almost any other programming language. The messages aren't always right on the money, but they can get you pretty close to the spot where the problem lies with minimal searching on your part.

Perl has myriad error messages, but a few definitely crop up more than others owing to some common typos that everyone seems to make. The following errors result from minor text-entry goofs that you can easily avoid.

Forgetting a semicolon

Probably the most common error message you see when programming in Perl looks something like this:

# syntax error, near "open"
File 'counter1.pl'; Line 10
# Execution aborted due to compilation errors.

You can look and look at Line 10, the one with the open statement, and you won't see anything wrong with it. The trick here is to examine the statement that comes before the open statement and see whether it ends with a semicolon. (Perl knows that a statement ends only when it encounters a semicolon.) In this case, the error is caused by a missing semicolon at the end of Line 7 of the program:

$TheFile = "sample.txt"

Forgetting a quotation mark

The following sort of error message can be extremely frustrating if you don't know of a quick fix:

# Bare word found where operator expected, near
# "open(INFILE, $TheFile) or die "The"
# (Might be a runaway multi-line " string starting on
# line 7)
File 'counter1.pl'; Line 10

This error is similar to forgetting a semicolon; instead, it's a quotation mark that's accidentally omitted:

$TheFile = "sample.txt;

In this case, Perl did a good job of guessing what is wrong, suggesting that a runaway multi-line " string on Line 7 is the problem, which is precisely right.

Entering one parenthesis too many or too few

When you have loads of opening and closing parentheses in a program, it's easy to slip an extra one in by accident. If that's the case, you may see a message from Perl that reads something like this:

# syntax error, near ") eq"
File 'counter1.pl'; Line 38
# syntax error, near "}"
File 'counter1.pl'; Line 42

Here, Perl can't determine where the error is exactly, but it actually got it right on the first guess: Line 38 contains an extra right parenthesis:

if(substr($TheLine, $CharPos, 1)) eq " ")

Having one parenthesis too few in a Perl program can cause harder-to-find problems:

# Can't use constant item as left arg of implicit -- >,
# near "1 }"
File 'counter1.pl'; Line 39
# Scalar found where operator expected, near "$CharPos"
File 'counter1.pl'; Line 40
# (Missing semicolon on previous line?)
# syntax error, near "$CharPos "
File 'counter1.pl'; Line 40

Yarp! All this was produced because the last parenthesis on Line 38 is missing:

if(substr($TheLine, $CharPos, 1) eq " "

Here is another good lesson in hunting down typing errors: Start where Perl says it found an error. If you don't find the error there, go up a line or two and see if the problem started earlier.

A final word of advice: Trust Perl to find the simple typos for you (where it can), and remember that it's giving you all the help it can, which is more than you can say for many programming languages.

[Sep 16, 2019] Switch Statements

Sep 16, 2019 | perldoc.perl.org

Starting from Perl 5.10.1 (well, 5.10.0, but it didn't work right), you can say

  1. use feature "switch" ;

to enable an experimental switch feature. This is loosely based on an old version of a Perl 6 proposal, but it no longer resembles the Perl 6 construct. You also get the switch feature whenever you declare that your code prefers to run under a version of Perl that is 5.10 or later. For example:

  1. use v5.14 ;

Under the "switch" feature, Perl gains the experimental keywords given , when , default , continue , and break . Starting from Perl 5.16, one can prefix the switch keywords with CORE:: to access the feature without a use feature statement. The keywords given and when are analogous to switch and case in other languages -- though continue is not -- so the code in the previous section could be rewritten as

  1. use v5.10.1 ;
  2. for ( $var ) {
  3. when ( /^abc/ ) { $abc = 1 }
  4. when ( /^def/ ) { $def = 1 }
  5. when ( /^xyz/ ) { $xyz = 1 }
  6. default { $nothing = 1 }
  7. }

The foreach is the non-experimental way to set a topicalizer. If you wish to use the highly experimental given , that could be written like this:

  1. use v5.10.1 ;
  2. given ( $var ) {
  3. when ( /^abc/ ) { $abc = 1 }
  4. when ( /^def/ ) { $def = 1 }
  5. when ( /^xyz/ ) { $xyz = 1 }
  6. default { $nothing = 1 }
  7. }

As of 5.14, that can also be written this way:

  1. use v5.14 ;
  2. for ( $var ) {
  3. $abc = 1 when /^abc/ ;
  4. $def = 1 when /^def/ ;
  5. $xyz = 1 when /^xyz/ ;
  6. default { $nothing = 1 }
  7. }

Or if you don't care to play it safe, like this:

  1. use v5.14 ;
  2. given ( $var ) {
  3. $abc = 1 when /^abc/ ;
  4. $def = 1 when /^def/ ;
  5. $xyz = 1 when /^xyz/ ;
  6. default { $nothing = 1 }
  7. }

The arguments to given and when are in scalar context, and given assigns the $_ variable its topic value.

Exactly what the EXPR argument to when does is hard to describe precisely, but in general, it tries to guess what you want done. Sometimes it is interpreted as $_ ~~ EXPR , and sometimes it is not. It also behaves differently when lexically enclosed by a given block than it does when dynamically enclosed by a foreach loop. The rules are far too difficult to understand to be described here. See Experimental Details on given and when later on.

Due to an unfortunate bug in how given was implemented between Perl 5.10 and 5.16, under those implementations the version of $_ governed by given is merely a lexically scoped copy of the original, not a dynamically scoped alias to the original, as it would be if it were a foreach or under both the original and the current Perl 6 language specification. This bug was fixed in Perl 5.18 (and lexicalized $_ itself was removed in Perl 5.24).

If your code still needs to run on older versions, stick to foreach for your topicalizer and you will be less unhappy.

[Sep 12, 2019] Why is Perl no longer a popular programming language - Quora

May 19, 2019 | www.quora.com
  1. die " Reports of my death are greatly exaggerated . \n "

Perl is alive and well, but it has steadily been losing promise over the past 20 years.

It's still heavily used for the tasks it was used for when I learnt it, in 1994–1995, but at that time, it looked set for an even brighter future: it was developing into one of the top-5 languages, a universal scripting language, a language you expect to find wherever scripting or dynamically typed languages are appropriate.

You can still find evidence of that today: some software has an extension API in Perl, some web applications are written in Perl, some larger system administration software is written in Perl, etcetera. But these systems are typically 20 years old. If you do this today, be prepared to justify yourself.

This is not because Perl has become any less suitable for doing these things. On the contrary, it has continued to improve. Yet, people have turned away from Perl, towards newer scripting languages such as Python, PHP, Ruby, and Lua, for tasks that in 1995 they would probably have used Perl for.

Why?

I believe the reason is simple: Perl is very free, syntactically and semantically. This makes it very good at what it was designed to do (scripting) but less suited for larger-scale programming.

Perl's syntactic freedom mostly originates from its mimicking idioms from other languages. It was designed to be a suitable replacement for other scripting languages, most notably the Bourne shell ( /bin/ sh ) and awk , so it adopts some of their idioms. This is perfect if you like these idioms for their compactness.

For instance, in the Bourne shell, we can write

  1. if mkdir $directory
  2. then
  3. echo successfully created directory : $directory
  4. elif test - d $directory
  5. then
  6. echo pre - existing directory : $directory
  7. else
  8. echo cannot create directory : $directory
  9. fi

In the Bourne shell, every statement is a Unix command invocation; in this case, test and mkdir . (Some commands, such as test , were built into the shell later.) Every command will succeed or fail, so we can use it in the condition of an if statement.

Now what if we only want to print a warning when something went wrong? We can write this:

  1. if mkdir $directory
  2. then
  3. : # nothing
  4. elif test - d $directory
  5. then
  6. : # nothing
  7. else
  8. echo cannot create directory : $directory
  9. fi

or we can combine the two conditions:

  1. if mkdir $directory || test - d $directory
  2. then
  3. : # nothing
  4. else
  5. echo cannot create directory : $directory
  6. fi

or we can combine them even further:

  1. mkdir $directory ||
  2. test - d $directory ||
  3. echo cannot create directory : $directory

These all do the same exact thing; clearly, the last version is the most compact. In a shell script with a lot of tests like this, writing things this way can save a considerable amount of space. Especially in throwaway scripts of a few lines, it's a lot easier to use more compact syntax.

Most programmers are familiar with seeing some special syntax for conditions in if statements. For this reason, Unix has the [ command, which scans its arguments for a matching ], and then invokes test with the arguments up to that point. So we can always replace

  1. test - d $directory

with

  1. [ - d $directory ]

in the pieces of code above. It means the same thing.

Now, Perl comes onto the scene. It is designed to be easy to replace Bourne shell scripts with. This is a very frequent use case for Perl, even today: I regularly find myself rewriting my Bourne shell scripts into Perl by going through them line by line.

So what do the Perl replacements of the above look like?

Here we go:

  1. if ( mkdir $directory )
  2. {
  3. # nothing
  4. } elsif (- d $directory )
  5. {
  6. # nothing
  7. } else {
  8. say "cannot create directory: $directory"
  9. }

or we can combine the two conditions:

  1. if ( mkdir $directory || - d $directory )
  2. {
  3. # nothing
  4. } else {
  5. say "cannot create directory: $directory"
  6. }

or we can combine them even further:

  1. mkdir $directory or
  2. - d $directory or
  3. say "cannot create directory: $directory"

As you can see, these are literal transliterations of the corresponding Bourne shell fragments.

In a language such as Java, you can use the first two forms, but not the third one. In such languages, there is a syntactic separation between expressions , which yield a value, and must be used in a context that demands such a value, and statements , which do not yield a value, and must be used in contexts that do not demand one. The third form is syntactically an expression, used in a context that demands a statement, which is invalid in such a language.

No such distinction is made in Perl, a trait it inherited from the Bourne shell, which in turn took it from Algol 68.

So here we have an example of syntactic freedom in Perl that many other languages lack, and in this case, Perl took it from the Bourne shell.

Allowing more compactness isn't the only reason for this freedom. The direct reason the Bourne shell doesn't make the distinction is that it relies on Unix commands, which do not make the distinction, either. Every Unix command can return a value (a return code) to indicate whether it failed and how. Therefore, it acts both as a statement and as a condition. There is a deeper reason behind this: concurrency.

For instance, when we want to create a directory, we can't separate doing it from testing whether it can/could be done. We could try and write something like

  1. if ( some test to see if we can mkdir $directory )
  2. then
  3. mkdir directory
  4. fi
  5. if ( some test to see if we managed to mkdir directory )
  6. then
  7. [...]
  8. fi

but that logic isn't correct. Unix is a multiprogramming environment, so anything could happen between our first test and our mkdir command, and before our mkdir command and the second test. Someone else might create that directory or remove it, or do something else that causes problems. Therefore, the only correct way to write code that tries to create a directory and determines whether it succeeds is to actually issue the mkdir command and check the value it returned. Which is what the constructs above do.

A shortcut like

  1. mkdir $directory or
  2. - d $directory or
  3. say "cannot create directory: $directory"

is just a consequence. Of course, you can still object to using it for stylistic reasons, but at least the construct makes sense once you know its origins.

Programmers who are unfamiliar with the paradigm of mixing statements and expressions, who have never seen any but the simplest of Bourne shell scripts, who have only been given programming tasks in which their program calls all the shots and nothing else can interfere, have never encountered a reason to treat statements and expressions as the same thing. They will be taken aback by a construct like this. I can't read this , they will mutter, it's incomprehensible gibberish . And if Perl is the first language they've seen that allows it, they will blame Perl. Only because they were never subjected to a large amount of Bourne shell scripting. Once you can read that, you can read anything ; Perl will look pretty tame in comparison.

Similar reasons can be given for most of the other syntactical freedom in Perl. I must say, Perl sometimes seems to make a point of being quirky, and I find some of the resulting oddities hard to justify, but they do make sense in context. The overall motivation is compactness. In scripting, where you type a lot and throw away a lot, the ability to write compact code is a great virtue.

Due to these syntactic quirks, Perl got a reputation for being a write-only language - meaning that when programmer A is faced with programmer B 's code, B may have used all kinds of idioms that A is unfamiliar with, causing delays for A . There is some truth to this, but the problem is exaggerated: syntax is the first thing you notice about a program, which is why it sticks out, but it's pretty superficial: new syntax really isn't so hard to learn.

So I'm not really convinced Perl's syntactic freedom is such a bad thing, except that people tend to blow it out of proportion.

However, Perl is also very free semantically : it is a truly dynamic language, allowing programmers to do all kinds of things that stricter languages forbid. For instance, I can monkey-patch functions and methods in arbitrary code that I'm using. This can make it very hard for programmers to understand how a piece of code is working, or whether it is working as intended.

This becomes more important when a software system grows larger or when others than the original author start to rely on it. The code doesn't just need to work, but it must be understandable to others. Consequently, in large, stable code bases, compactness and freedom of expression are less important than consistency, a smooth learning curve for beginners, and protection against routine errors. Therefore, many software development teams prefer languages such as Java, with its very limited syntactic freedom and strict compile-time type checking. Perl is at the opposite end of the spectrum, with its extreme syntactic and semantic freedom.

This wouldn't be a problem if there were ways to straitjacket Perl if you wanted to; if there was a way to say: for this project, be as rigid as Java syntactically or semantically; I want as few surprises as possible in code that I didn't write. Sure enough, Perl has support for compile-time checking ( use strict ; use warnings , and the perlcritic utility) and consistent code formatting (the perltidy utility), but they were added as afterthoughts and cannot come anywhere near the level of strictness a Java programmer would expect.

To support that, the language needed to be redesigned from scratch, and the result would be incompatible with the original. This effort has been made, producing Perl 6, but in the meantime, many other languages sprung up and became popular for the cases Perl programmers wanted to use Perl for, and if you're going to switch to an incompatible language anyway, why not use one of those instead?

[Sep 12, 2019] CMOS #12- Randal Schwartz the host of FLOSS Weekly

The fate of Perl 6 is unclear but Perl 5.10 is here to stay. Some thing were screwed after Perl 5.10, but they might be eventually corrected. OO-enthusiasts did a every bad service to Perl trying to enforce unsuitable for programming, say, utilities paradigm on everybody. That led to huge inefficiencies and bloated difficult to maintain code. That also somewhat devalued Perl standard library as the conversion to OO spoiled the broth.
Notable quotes:
"... I'm keeping up with Perl, but not really, I still see a feature, like in Perl 5.16, and I go, Oh, that's in relatively modern Perl, no wonder I don't know about it. I think of Perl as whatever was back in 5.10 and 5.12, that's the latest that I was writing my books for, my trainings for. ..."
"... So the stuff that's coming out in 5.18 and 5.20 and 5.22 now, is sort of beyond me, I just can't keep up with Perl-delta, and that's a scary thing for the number one prolific author about Perl, to not be able to keep up with what's happening in the Perl community, this is clearly an indication that Perl is alive and well, and I've kind of missed the boat, now. ..."
"... And every time I go to YAPC or some other place where they're talking about Perl 6, I get excited about it, for all of a month, and then I come back and then I go, How am I going to use this practically? None of my current clients are demanding that. ..."
Sep 12, 2019 | code-maven.com

09:24 Randal Schwartz

Yeah, I think a few years ago, it was all about cloud stuff. So it was all about running your application in cloud. Starting probably a couple years ago, with the Docker revolution, it's all about containers now.

But we're also seeing a revolution in smart, JavaScript-based ultimately, front-ends, that are doing things like single-page applications and stuff, and I'm really pretty excited about that. Not that I ever really wanted to spend a lot of time playing with JavaScript, but unfortunately I guess that that's a requirement, so I'm continuing to hone my JavaScript skills.

I'm also honing my Dart skills, because that language out of Google, is really gaining some traction, in terms of being able to do server-side stuff, essentially replacing Node.JS with a reasonable language. And also client-side stuff for all the modern browsers, and it translating down into JavaScript, so as long as there's a reasonable ECMA 5 or something available in the browser, Dart works really nicely. But Dart looks closer, as a language, to something like Java, with optional typing, so if you add types to variables, you can actually get hints from your development environment and that's pretty slick. So I'm learning Dart in the background, I actually have a couple applications for it already, that as I learn more, I'll be able to deploy. I'm also learning things like Angular , so I can have reactive front-ends, and again, it's like there's not enough hours in the day for me to learn everything I want to learn.

I'm keeping up with Perl, but not really, I still see a feature, like in Perl 5.16, and I go, Oh, that's in relatively modern Perl, no wonder I don't know about it. I think of Perl as whatever was back in 5.10 and 5.12, that's the latest that I was writing my books for, my trainings for.

So the stuff that's coming out in 5.18 and 5.20 and 5.22 now, is sort of beyond me, I just can't keep up with Perl-delta, and that's a scary thing for the number one prolific author about Perl, to not be able to keep up with what's happening in the Perl community, this is clearly an indication that Perl is alive and well, and I've kind of missed the boat, now.

17:53 Gabor Szabo Yeah, so as a closing question, I would like to go back a little bit to the languages and the things you do with open source, and ask you, where are you heading? Are you going to go back to Perl and learn what the new things in Perl are, or are you more interested in other languages, and which ones?

18:16 Randal Schwartz

Well, I download and compile Perl 6 every day. And every time I go to YAPC or some other place where they're talking about Perl 6, I get excited about it, for all of a month, and then I come back and then I go, How am I going to use this practically? None of my current clients are demanding that.

Clearly if I were to write training materials for that, I'd have to present it at least to 200 people, whether that's 10 classes of 20, or a giant 200 person week-end event, that's sort of the minimum for amortizing the inception cost for any class that I've ever written. So I use the 200 number as kind of a rule of thumb.

And I just don't see that happening, I don't see getting enough people together in the right places, to be able to do that. So I continue to watch what people are doing with Perl 6, I continue compiling it every day, and I'd love for it to become extremely popular so I could go back to that, and say I could continue my Perl heritage.

But, as I mentioned earlier, I think Dart has legs. Given that Google's behind it, given that Google and a number of other companies are already deploying public-facing projects in it. Given that it does compile down and work in all modern browsers, I easily see the need for like rent a hotel room for a weekend and have 20, 50, 100 people show up to learn about it, because single-page applications are all the rage right now, and Dart is a really solid language for that, and Google is betting on that.

You may say, Where is Go in that equation? Go is great for server-side stuff, and great for the kind of things they're doing on back-ends, and although Dart can also do back-end stuff, essentially replacing Node.JS for that sort of thing, and have a single language for both back-end and front-end. Dart's real win is in the front-end, being able to be transpiled over to JavaScript and being able to scale to hundreds of thousands of lines of code for some of their larger applications. I think that's got legs, I'm in on the groundfloor, like I was on Perl, I'm already recognized among the Dart people as being someone who can put things together. I did a one-hour long intro to Dart talk that was reviewed by some of the key people in the Dart community, and they really like what I did with it, so I seem to have, again, that knack for finding something complex and finding the simplest ends of it, and I'm already there with Dart.

And also, the whole Fuchsia announcement a few weeks ago, where Google's coming out with this language for real-time operating systems, and it has a strong Dart component in it. I think that's another thing that says, say if they start putting that in Google Glass , or if they even put that as a replacement for the Android operating system, or for Google Chrome, which some people are suspecting that this is all amalgamation of it.

Especially when somebody's looking at the source code the other day, and it has a lot of files, not only from Android, but also from the old Be OS , which was sort of the predecessor of what eventually became OS X, kind of interesting that that's part of that project as well.

So with Fuchsia on the horizon, with Dart already being deployed by numbers of people, with me having a knack for understanding how Dart actually works, given that it was also built by some of the key players in Smalltalk, which I go back 16 years with, I think this is probably the right place for me to look at my future.

22:02 Gabor Szabo And I guess, FLOSS Weekly?

22:05 Randal Schwartz

FLOSS Weekly will continue.

In fact I just had a converstaion recently with Leo, we're one of the smaller shows on the network, but he's absolutely committed to this show. He likes what I'm doing with it, he likes the directions I'm taking it, he likes the team I've put together, who were able to pick up the show, even when I was absent for six weeks, in the hospital recently, without notice unfortunately, I guess that's always the way you end up in the hospital.

So my team picked up, and Aaron Newcomb did a great job of hosting while I was gone, but Leo likes the team I've built and Leo likes the kinds of guests I'm getting on, the variety especially. I've had a lot of people write in and say, I don't always want or understand the thing you're talking about, but I listen to the way you interview them, and I listen to the things you're able to pull out, like what's the governance model, how are you making money with this, what got you started? These sorts of things are really sort of cross-project. You know, you can learn that sort of stuff about anything you want to start, and like I said, I learned a lot already by doing this show and so a lot of the audience is picking that up. And we have a fun time.

I tell jokes sometimes and I have a bad way of making really bad puns. And that's kind of the way it works but I really enjoy the show, I'm going to keep doing it. And I told Leo I would just keep doing this as long as he let's me, and he goes, Well then, that makes two of us. So we'll still be doing this in 20 years, if they let us. And I said, That sounds like a great promise, Leo, thank you. So yeah, I'll be doing FLOSS Weekly for at least awhile longer.

23:45 Gabor Szabo I'm happy to hear that and I hope to see a lot more of that. And I hope to see you somewhere, I don't know, maybe at a Dart conference?

23:56 Randal Schwartz

Yeah, that'd be awesome!

And I think you come to OSCon , occasionally, or maybe, well I've got to get out to a YAPC::Europe or a YAPC::Israel or something at some point, but just haven't made those yet. I think it's partially because I need to figure out what to pitch to the Perl conference.

Oh wait, I could just be press again! That's the other thing, is that FLOSS Weekly has allowed me to apply as press for OSCon for the last few years, even though I don't have an actual talk to give. And Red Hat actually invited me to their conference, as press. And I thought, Well, that's the first time that's happened. That really says I've made it. That really says that FLOSS Weekly is recognized as legitimate press. So I'm wearing a whole 'nother hat, so my hat tree of all my hats, hanging up in the corner, has gotten a whole 'nother rung.

[Sep 12, 2019] prename -- rename files using any perl expressior (regex, tr, etc)

Sep 12, 2019 | gist.githubusercontent.com
#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#
#  This script is free software; you can redistribute it and/or modify it
#  under the same terms as Perl itself.
#
# Larry(?)'s RCS header:
#  RCSfile: rename,v   Revision: 4.1   Date: 92/08/07 17:20:30 
#
# $RCSfile: rename,v $$Revision: 1.5 $$Date: 1998/12/18 16:16:31 $
#
# $Log: rename,v $
# Revision 1.5  1998/12/18 16:16:31  rmb1
# moved to perl/source
# changed man documentation to POD
#
# Revision 1.4  1997/02/27  17:19:26  rmb1
# corrected usage string
#
# Revision 1.3  1997/02/27  16:39:07  rmb1
# added -v
#
# Revision 1.2  1997/02/27  16:15:40  rmb1
# *** empty log message ***
#
# Revision 1.1  1997/02/27  15:48:51  rmb1
# Initial revision
#

use strict;

use Getopt::Long;
Getopt::Long::Configure('bundling');

my ($verbose, $no_act, $force, $op);

die "Usage: rename [-v] [-n] [-f] perlexpr [filenames]\n"
    unless GetOptions(
        'v|verbose' => \$verbose,
        'n|no-act'  => \$no_act,
        'f|force'   => \$force,
    ) and $op = shift;

$verbose++ if $no_act;

if (!@ARGV) {
    print "reading filenames from STDIN\n" if $verbose;
    @ARGV = ;
    chop(@ARGV);
}

for (@ARGV) {
    my $was = $_;
    eval $op;
    die $@ if $@;
    next if $was eq $_; # ignore quietly
    if (-e $_ and !$force)
    {
        warn  "$was not renamed: $_ already exists\n";
    }
    elsif ($no_act or rename $was, $_)
    {
        print "$was renamed as $_\n" if $verbose;
    }
    else
    {
        warn  "Can't rename $was $_: $!\n";
    }
}

__END__

=head1 NAME

rename - renames multiple files

=head1 SYNOPSIS

B S ]> S ]> S ]> I S ]>

=head1 DESCRIPTION

C
renames the filenames supplied according to the rule specified as the
first argument.
The I 
argument is a Perl expression which is expected to modify the C
string in Perl for at least some of the filenames specified.
If a given filename is not modified by the expression, it will not be
renamed.
If no filenames are given on the command line, filenames will be read
via standard input.

For example, to rename all files matching C to strip the extension,
you might say

        rename 's/\.bak$//' *.bak

To translate uppercase names to lower, you'd use

        rename 'y/A-Z/a-z/' *

=head1 OPTIONS

=over 8

=item B, B

Verbose: print names of files successfully renamed.

=item B, B

No Action: show what files would have been renamed.

=item B, B

Force: overwrite existing files.

=back

=head1 ENVIRONMENT

No environment variables are used.

=head1 AUTHOR

Larry Wall

=head1 SEE ALSO

mv(1), perl(1)

=head1 DIAGNOSTICS

If you give an invalid Perl expression you'll get a syntax error.

=head1 BUGS

The original C did not check for the existence of target filenames,
so had to be used with care.  I hope I've fixed that (Robin Barker).

=cut



[Sep 10, 2019] Perl Modules and namespaces

javatpoint

A module is a container which holds a group of variables and subroutines which can be used in a program. Every module has a public interface, a set of functions and variables.

To use a module into your program, require or use statement can be used, although their semantics are slightly different.

The 'require' statement loads module at runtime to avoid redundant loading of module. The 'use' statement is like require with two added properties, compile time loading and automatic importing.

Namespace is a container of a distinct set of identifiers (variables, functions). A namespace would be like name::variable .

Every piece of Perl code is in a namespace.

In the following code,

  1. use strict;
  2. use warnings;
  3. my $x = "Hello" ;
  4. $main ::x = "Bye" ;
  5. print "$main::x\n" ; # Bye
  6. print "$x\n" ; # Hello

Here are two different variables defined as x . the $main::x is a package variable and $x is a lexical variable. Mostly we use lexical variable declared with my keyword and use namespace to separate functions.

In the above code, if we won't use use strict , we'll get a warning message as

  1. Name "main::x" used only once: possible typo at line..

The main is the namespace of the current script and of current variable. We have not written anything and yet we are already in the 'main' namespace.

By adding 'use strict', now we got the following error,

  1. Global symbol "$x" requires explicit package name

In this error, we got a new word 'package'. It indicates that we forgot to use 'my' keyword before declaring variable but actually it indicates that we should provide name of the package the variable resides in.


Perl Switching namespace using package keyword

Look at the following code,

  1. use strict;
  2. use warnings;
  3. use 5.010;
  4. sub hii {
  5. return "main" ;
  6. }
  7. package two;
  8. sub hii {
  9. return "two" ;
  10. }
  11. say main::hii(); # main
  12. say two::hii(); # two
  13. say hii(); # two
  14. package main;
  15. say main::hii(); # main
  16. say two::hii(); # two
  17. say hii(); # main

Here we are using package keyword to switch from 'main' namespace to 'two' namespace.

Calling hii() with namespaces returns respective namespaces. Like , say main::hii(); returns 'main' and say two::hii(); returns 'two'.

Calling hii() without namespace prefix, returns the function that was local to the current namespace. In first time, we were in 'two' namespace. Hence it returned 'two'. In second time, we switched the namespace using package main. Hence it returns 'main'.

[Sep 10, 2019] Use of uninitialized value

Sep 10, 2019 | perlmaven.com

Prev Next This is one of the most common warning you will encounter while running Perl code.

It is a warning, it won't stop your script from running and it is only generated if warnings were turned on. Which is recommended.

The most common way to turn on warnings is by including a use warnings; statement at the beginning of your script or module.

Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!

The older way is adding a -w flag on the sh-bang line. Usually looks like this as the first line of your script:

#!/usr/bin/perl -w

There are certain differences, but as use warnings is available for 12 years now, there is no reason to avoid it. In other words:

Always use warnings; !

Let's go back to the actual warning I wanted to explain.

A quick explanation
Use of uninitialized value $x in say at perl_warning_1.pl line 6.

This means the variable $x has no value (its value is the special value undef ). Either it never got a value, or at some point undef was assigned to it.

You should look for the places where the variable got the last assignment, or you should try to understand why that piece of code has never been executed.

A simple example

The following example will generate such warning.

  1. use warnings ;
  2. use strict ;
  3. use 5.010 ;
  4. my $x ;
  5. say $x ;

Perl is very nice, tells us which file generated the warning and on which line.

Only a warning

As I mentioned this is only a warning. If the script has more statements after that say statement, they will be executed:

  1. use warnings ;
  2. use strict ;
  3. use 5.010 ;
  4. my $x ;
  5. say $x ;
  6. $x = 42 ;
  7. say $x ;

This will print

Use of uninitialized value $x in say at perl_warning_1.pl line 6.

42
Confusing output order

Beware though, if your code has print statements before the line generating the warning, like in this example:

  1. use warnings ;
  2. use strict ;
  3. use 5.010 ;
  4. print 'OK' ;
  5. my $x ;
  6. say $x ;
  7. $x = 42 ;
  8. say $x ;

the result might be confusing.

Use of uninitialized value $x in say at perl_warning_1.pl line 7.
OK
42

Here, 'OK', the result of the print is seen after the warning, even though it was called before the code that generated the warning.

This strangeness is the result of IO buffering . By default Perl buffers STDOUT, the standard output channel, while it does not buffer STDERR, the standard error channel.

So while the word 'OK' is waiting for the buffer to be flushed, the warning message already arrives to the screen.

Turning off buffering

In order to avoid this you can turn off the buffering of STDOUT.

This is done by the following code: $| = 1; at the beginning of the script.

  1. use warnings ;
  2. use strict ;
  3. use 5.010 ;
  4. $ | = 1 ;
  5. print 'OK' ;
  6. my $x ;
  7. say $x ;
  8. $x = 42 ;
  9. say $x ;
OKUse of uninitialized value $x in say at perl_warning_1.pl line 7.
42

(The warning is on the same line as the OK because we have not printed a newline \n after the OK.)

The unwanted scope
  1. use warnings ;
  2. use strict ;
  3. use 5.010 ;
  4. my $x ;
  5. my $y = 1 ;
  6. if ( $y ) {
  7. my $x = 42 ;
  8. }
  9. say $x ;

This code too produces Use of uninitialized value $x in say at perl_warning_1.pl line 11.

I have managed to make this mistake several times. Not paying attention I used my $x inside the if block, which meant I have created another $x variable, assigned 42 to it just to let it go out of the scope at the end of the block. (The $y = 1 is just a placeholder for some real code and some real condition. It is there only to make this example a bit more realistic.)

There are of course cases when I need to declare a variable inside an if block, but not always. When I do that by mistake it is painful to find the bug.

[Sep 10, 2019] How do I avoid an uninitialized value

Sep 10, 2019 | stackoverflow.com

marto ,Jul 15, 2011 at 16:52

I use this scrub function to clean up output from other functions.
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my %h = (
    a => 1,
    b => 1
    );

print scrub($h{c});

sub scrub {
    my $a = shift;

    return ($a eq '' or $a eq '~' or not defined $a) ? -1 : $a;
}

The problem occurs when I also would like to handle the case, where the key in a hash doesn't exist, which is shown in the example with scrub($h{c}) .

What change should be make to scrub so it can handle this case?

Sandra Schlichting ,Jun 22, 2017 at 19:00

You're checking whether $a eq '' before checking whether it's defined, hence the warning "Use of uninitialized value in string eq". Simply change the order of things in the conditional:
return (!defined($a) or $a eq '' or $a eq '~') ? -1 : $a;

As soon as anything in the chain of 'or's matches, Perl will stop processing the conditional, thus avoiding the erroneous attempt to compare undef to a string.

Sandra Schlichting ,Jul 14, 2011 at 14:34

In scrub it is too late to check, if the hash has an entry for key key . scrub() only sees a scalar, which is undef , if the hash key does not exist. But a hash could have an entry with the value undef also, like this:
my %h = (
 a => 1,
 b => 1,
 c => undef
);

So I suggest to check for hash entries with the exists function.

[Sep 10, 2019] How do I check if a Perl scalar variable has been initialized - Stack Overflow

Sep 10, 2019 | stackoverflow.com

How do I check if a Perl scalar variable has been initialized? Ask Question Asked 8 years, 11 months ago Active 3 years ago Viewed 49k times 33 10


brian d foy ,Sep 18, 2010 at 13:53

Is the following the best way to check if a scalar variable is initialized in Perl, using defined ?
my $var;

if (cond) {
    $var = "string1";
}

# Is this the correct way?
if (defined $var) {
    ...
}

mob ,Sep 25, 2010 at 21:35

Perl doesn't offer a way to check whether or not a variable has been initialized.

However, scalar variables that haven't been explicitly initialized with some value happen to have the value of undef by default. You are right about defined being the right way to check whether or not a variable has a value of undef .

There's several other ways tho. If you want to assign to the variable if it's undef , which your example code seems to indicate, you could, for example, use perl's defined-or operator:

$var //= 'a default value';

vol7ron ,Sep 17, 2010 at 23:17

It depends on what you're trying to do. The proper C way to do things is to initialize variables when they are declared; however, Perl is not C , so one of the following may be what you want:
  1)   $var = "foo" unless defined $var;      # set default after the fact
  2)   $var = defined $var? $var : {...};     # ternary operation
  3)   {...} if !(defined $var);              # another way to write 1)
  4)   $var = $var || "foo";                  # set to $var unless it's falsy, in which case set to 'foo'
  5)   $var ||= "foo";                        # retain value of $var unless it's falsy, in which case set to 'foo' (same as previous line)
  6)   $var = $var // "foo";                  # set to $var unless it's undefined, in which case set to 'foo'
  7)   $var //= "foo";                        # 5.10+ ; retain value of $var unless it's undefined, in which case set to 'foo' (same as previous line)


C way of doing things ( not recommended ):

# initialize the variable to a default value during declaration
#   then test against that value when you want to see if it's been changed
my $var = "foo";
{...}
if ($var eq "foo"){
   ... # do something
} else {
   ... # do something else
}

Another long-winded way of doing this is to create a class and a flag when the variable's been changed, which is unnecessary.

Axeman ,Sep 17, 2010 at 20:39

If you don't care whether or not it's empty, it is. Otherwise you can check
if ( length( $str || '' )) {}

swilliams ,Sep 17, 2010 at 20:53

It depends on what you plan on doing with the variable whether or not it is defined; as of Perl 5.10, you can do this (from perl51000delta ):

A new operator // (defined-or) has been implemented. The following expression:

 $a // $b

is merely equivalent to

defined $a ? $a : $b

and the statement

$c //= $d;

can now be used instead of

$c = $d unless defined $c;

rafl ,Jun 24, 2012 at 7:53

'defined' will return true if a variable has a real value.

As an aside, in a hash, this can be true:

if(exists $h{$e} && !defined $h{$e})

[Sep 10, 2019] Perl Multidimensional Array

Sep 10, 2019 | www.javatpoint.com

The multi dimensional array is represented in the form of rows and columns, also called Matrix.

They can not hold arrays or hashes, they can only hold scalar values. They can contain references to another arrays or hashes.


Perl Multidimensional Array Matrix Example

Here, we are printing a 3 dimensional matrix by combining three different arrays arr1 , arr2 and arr3 . These three arrays are merged to make a matrix array final .

Two for loops are used with two control variables $i and $j .

  1. ## Declaring arrays
  2. my @arr1 = qw(0 10 0);
  3. my @arr2 = qw(0 0 20);
  4. my@arr3 = qw(30 0 0);
  5. ## Merging all the single dimensional arrays
  6. my @final = (\@arr1, \@arr2, \@arr3);
  7. print "Print Using Array Index\n" ;
  8. for (my $i = 0; $i <= $#final; $i ++){
  9. # $#final gives highest index from the array
  10. for (my $j = 0; $j <= $#final ; $j ++){
  11. print "$final[$i][$j] " ;
  12. }
  13. print "\n" ;
  14. }

Output:

Print Using Array Index
0 10 0
0 0 20 
30 0 0

Perl Multidimensional Array Initialization and Declaration Example

In this example we are initializing and declaring a three dimensional Perl array .

  1. @ array = (
  2. [1, 2, 3],
  3. [4, 5, 6],
  4. [7, 8, 9]
  5. );
  6. for ( $i = 0; $i < 3; $i ++) {
  7. for ( $j = 0; $j < 3; $j ++) {
  8. print "$array[$i][$j] " ;
  9. }
  10. print "\n" ;
  11. }

Output:

1 2 3
4 5 6 
7 8 9

[Sep 10, 2019] Perl Hashes - javatpoint

Sep 10, 2019 | www.javatpoint.com

The hashes is the most essential and influential part of the perl language. A hash is a group of key-value pairs. The keys are unique strings and values are scalar values.

Hashes are declared using my keyword. The variable name starts with a (%) sign.

Hashes are like arrays but there are two differences between them. First arrays are ordered but hashes are unordered. Second, hash elements are accessed using its value while array elements are accessed using its index value.

No repeating keys are allowed in hashes which makes the key values unique inside a hash. Every key has its single value.

Syntax:

  1. my %hashName = (
  2. "key" => "value" ;
  3. )

Perl Hash Accessing

To access single element of hash, ($) sign is used before the variable name. And then key element is written inside {} braces.

  1. my %capitals = (
  2. "India" => "New Delhi" ,
  3. "South Korea" => "Seoul" ,
  4. "USA" => "Washington, D.C." ,
  5. "Australia" => "Canberra"
  6. );
  7. print "$capitals{'India'}\n" ;
  8. print "$capitals{'South Korea'}\n" ;
  9. print "$capitals{'USA'}\n" ;
  10. print "$capitals{'Australia'}\n" ;

Output:

New Delhi
Seoul
Washington, D.C.
Canberra

Perl Hash Indexing

Hashes are indexed using $key and $value variables. All the hash values will be printed using a while loop. As the while loop runs, values of each of these variables will be printed.

  1. my %capitals = (
  2. "India" => "New Delhi" ,
  3. "South Korea" => "Seoul" ,
  4. "USA" => "Washington, D.C." ,
  5. "Australia" => "Canberra"
  6. );
  7. # LOOP THROUGH IT
  8. while (( $key , $value ) = each(%capitals)){
  9. print $key . ", " . $value . "\n" ;
  10. }

Output:

Australia, Canberra
India, New Delhi
USA, Washington, D.C.
South Korea, Seoul

Perl sorting Hash by key

You can sort a hash using either its key element or value element. Perl provides a sort() function for this. In this example, we'll sort the hash by its key elements.

  1. my %capitals = (
  2. "India" => "New Delhi" ,
  3. "South Korea" => "Seoul" ,
  4. "USA" => "Washington, D.C." ,
  5. "Australia" => "Canberra"
  6. );
  7. # Foreach loop
  8. foreach $key (sort keys %capitals) {
  9. print "$key: $capitals{$key}\n" ;
  10. }

Output:

Australia: Canberra
India: New Delhi
South Korea: Seoul
USA: Washington: D.C.

Look at the output, all the key elements are sorted alphabetically.


Perl sorting Hash by its value

Here we'll sort hash by its value elements.

  1. my %capitals = (
  2. "India" => "New Delhi" ,
  3. "South Korea" => "Seoul" ,
  4. "USA" => "Washington, D.C." ,
  5. "UK" => "London"
  6. );
  7. # Foreach loop
  8. foreach $value (sort { $capitals { $a } cmp $capitals { $b } }
  9. keys %capitals)
  10. {
  11. print "$value $capitals{$value}\n" ;
  12. }

Output:

UK London
India New Delhi
South Korea Seoul
USA Washington D.C.

Look at the output, all the value elements are sorted alphabetically.

... ... ...


Perl Removing Hash Elements

To remove a hash element, use delete() function.

Here, we have removed both the key-value pairs which were added in the last example.

  1. my %capitals = (
  2. "India" => "New Delhi" ,
  3. "South Korea" => "Seoul" ,
  4. "USA" => "Washington, D.C." ,
  5. "Australia" => "Canberra"
  6. "Germany " => " Berlin"
  7. " UK " => "London"
  8. );
  9. while (( $key , $value ) = each(%apitals)){
  10. print $key . ", " . $value . "\n" ;
  11. }
  12. #removing element
  13. delete ( $capitals {Germany});
  14. delete ( $capitals {UK});
  15. # Printing new hash
  16. print "\n" ;
  17. while (( $key , $value ) = each(%capitals)){
  18. print $key . ", " . $value . "\n" ;
  19. }

Output:

Australia, Canberra
India, New Delhi
USA, Washington D.C.
South Korea, Seoul

Perl deleting Vs Undefining Hash Elements

deleting: In deleting, key-value pair will be deleted from the hash.

Syntax:

  1. delete ( $hash { $key });

undef: In undef, the value will be undefined but key will remain in the hash.

Syntax:

  1. undef $hash { $key };

[Sep 10, 2019] Pro Perl Debugging

May 12, 2012 | Slashdot

This title was published in hardcover in March 2005 by Apress, a relatively new member of the technical publishing world. The publisher has a Web page for the book that includes links to all of the source code in a Zip file, the table of contents in PDF format, and a form for submitting errata. The book comprises 269 pages, the majority of which are organized into 16 chapters:

Introduction (not to be confused with the true Introduction immediately preceding it),

Inspecting Variables and Getting Help, Controlling Program Execution, Debugging a Simple Command Line Program, Tracing Execution, Debugging Modules, Debugging Object-Oriented Perl, Using the Debugger As a Shell, Debugging a CGI Program, Perl Threads and Forked Processes, Debugging Regular Expressions, Debugger Customization, Optimization and Performance Hints and Tips, Command Line and GUI Debuggers, Comprehensive Command Reference, Book References and URLs.

hattmoward ( 695554 ) , Monday December 12, 2005 @02:11PM ( #14240507 )

Re:In defense of print statements ( Score: 5 , Insightful)

How many times is that conditional checked at runtime? They can add up. In perl, you could have it optimized away at compile time...

sub DEBUG() { return 1; }

...

DEBUG and print "value of blah:", $blah, $/;

but... TIMTOWTDI ;)
Mark_Uplanguage ( 444809 ) , Monday December 12, 2005 @03:13PM ( #14241006 )
Re:In defense of print statements ( Score: 4 , Informative)

When debugging I emphasize the use of "warn" over "print". It's the same syntax, but the warn statements don't get spooled and therefore their timing is quicker.

This is vital when you code just plain blows up. Using "print" means that a statement which got executed before the disaster may not make it to console, thus leading you to believe that it never got executed. "warn" avoids this problem and thus leads you to the problem more accurately. It also makes it easy to globally comment out the warn statements before going releasing the code.

codyk ( 857932 ) , Monday December 12, 2005 @03:20PM ( #14241071 )
Re:In defense of print statements ( Score: 1 )

Or you could just . . .

use Smart::Comments;
### Expected: "a bunch o stuff" Got: $stuff

. . . and have debugging statements that are easier to write, can be turned off in one place, and don't waste efficiency checking a bunch of conditionals.
see http://search.cpan.org/~dconway/Smart-Comments-1. 0 .1/lib/Smart/Comments.pm [cpan.org]

licamell ( 778753 ) * , Monday December 12, 2005 @01:47PM ( #14240302 )
use strict and Data::Dumper! ( Score: 5 , Insightful)

#! /usr/local/bin/perl
#
# Two things that make debugging perl easy:
#

use strict;
use Data::Dumper; ›

Baron von Leezard ( 675918 ) , Monday December 12, 2005 @03:22PM ( #14241092 )
Re:use strict and Data::Dumper! ( Score: 1 )

[That's one freelance Perl programmer I'll have to remember never to hire.]

Seriously, I'm one of those people who use a debugger every day. Actually, when I write new code in Perl, often the first thing I do is step through it in the debugger to make sure it does what I think it should. Especially in Perl, it is very easy to accidentally do something that's a little off. With the "wait until something goes wrong before I investigate" attitude demonstrated here, you'll never know anything is amiss until some nasty bug crops up as a result. Using the debugger to sanity check my code means that I catch most bugs before they ever cause problems.

I'm sure I'm going to get some snide remarks about this approach, but really, I've been a serious Perl programmer for about eight years now, and often write moderately complex Perl programs that work perfectly the first time--run through the debugger or not. I can't say that about any other language, and it's something most people can't say about any language, let alone Perl ;)

[Sep 10, 2019] logging - Perl - Output the log files - Stack Overflow

Aug 27, 2015 | stackoverflow.com

Perl - Output the log files Ask Question Asked 4 years ago Active 4 years ago Viewed 3k times 1 2


Arunesh Singh ,Aug 27, 2015 at 8:53

I have created a perl that telnet to multiple switches. I would like to check if telnet functions properly by telneting the switch.

This is my code to telnet to the switches:

#!/usr/bin/perl
use warnings;
use Net::Cisco;

open( OUTPUT, ">log.txt" );
open( SWITCHIP, "ip.txt" ) or die "couldn't open ip.txt";

my $count = 0;

while (<SWITCHIP>) {
    chomp($_);
    my $switch = $_;
    my $tl     = 0;
    my $t      = Net::Telnet::Cisco->new(
        Host => $switch,
        Prompt =>
            '/(?m:^(?:[\w.\/]+\:)?[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
        Timeout => 5,
        Errmode => 'return'
    ) or $tl = 1;

    my @output = ();
    if ( $tl != 1 ) {
        print "$switch Telnet success\n";
    }
    else {
        my $telnetstat = "Telnet Failed";
        print "$switch $telnetstat\n";
    }
    close(OUTPUT);
    $count++;
}

This is my output status after I was testing 7 switches:

10.xxx.3.17 Telnet success
10.xxx.10.12 Telnet success
10.xxx.136.10 Telnet success
10.xxx.136.12 Telnet success
10.xxx.188.188 Telnet Failed
10.xxx.136.13 Telnet success

I would like to convert the telnet result as log file.
How to separate successful and failed telnet results by using perl?

Danny Luk ,Aug 28, 2015 at 8:40

Please Try the following
#!/usr/bin/perl
use warnings;
use Net::Cisco;
################################### S
open( OUTPUTS, ">log_Success.txt" );
open( OUTPUTF, ">log_Fail.txt" );
################################### E
open( SWITCHIP, "ip.txt" ) or die "couldn't open ip.txt";

my $count = 0;

while (<SWITCHIP>) {
    chomp($_);
    my $switch = $_;
    my $tl     = 0;
    my $t      = Net::Telnet::Cisco->new(
        Host => $switch,
        Prompt =>
            '/(?m:^(?:[\w.\/]+\:)?[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
        Timeout => 5,
        Errmode => 'return'
    ) or $tl = 1;

    my @output = ();
################################### S
    if ( $tl != 1 ) {
        print "$switch Telnet success\n"; # for printing it in screen
        print OUTPUTS "$switch Telnet success\n"; # it will print it in the log_Success.txt
    }
    else {
        my $telnetstat = "Telnet Failed";
        print "$switch $telnetstat\n"; # for printing it in screen
        print OUTPUTF "$switch $telnetstat\n"; # it will print it in the log_Fail.txt
    }
################################### E
    $count++;
}
################################### S
close(SWITCHIP);
close(OUTPUTS);
close(OUTPUTF);
################################### E

Danny Luk ,Aug 28, 2015 at 8:39

In print statement after print just write the filehandle name which is OUTPUT in your code:
print OUTPUT "$switch Telnet success\n";

and

print OUTPUT "$switch $telnetstat\n";

A side note: always use a lexical filehandle and three arguments with error handling to open a file. This line open(OUTPUT, ">log.txt"); you can write like this:

open my $fhout, ">", "log.txt" or die $!;

Sobrique ,Aug 28, 2015 at 8:39

Use Sys::Syslog to write log messages.

But since you're opening a log.txt file with the handle OUTPUT , just change your two print statements to have OUTPUT as the first argument and the string as the next (without a comma).

my $telnetstat;
if($tl != 1) {
  $telnetstat = "Telnet success";
} else {
  $telnetstat = "Telnet Failed";
}
print OUTPUT "$switch $telnetstat\n";

# Or the shorter ternary operator line for all the above:
print OUTPUT $swtich . (!$tl ? " Telnet success\n" : " Telnet failed\n");

You might consider moving close to an END block:

END {
  close(OUTPUT);
}

Not only because it's in your while loop.

[Sep 02, 2019] perlcperl - a perl5 with classes, types, compilable, company friendly

Sep 02, 2019 | perl11.org

Compile-time optimizations

cperl adds many more traditional compile-time optimizations: more and earlier constant folding, type promotions, shaped arrays, usage of literal and typed constants, loop unrolling, omit unnecessary array bounds checks, function inlining and conversion of static method calls to functions.

Perl 5 only inlines constant function bodies with an explicit empty () prototype.

    sub x() {1+2} # inlined in perl5
    sub x   {1+2} # inlined in cperl only

cperl inlines constant function bodies even without empty prototype declaration, has type declarations for most internal ops, and optimizes these ops depending on the argument types; currently for all arithmetic unops and binops, and the data-accessing ops padsv, svop, and sassign. opnames.h stores PL_op_type_variants , all possible type promotions for each op. opcode.h stores PL_op_type with the type declarations of all ops.

[Sep 02, 2019] This Perl Goes To 11

Sep 02, 2019 | perl11.org

Perl 11 is not (yet) an actual version of Perl; rather, Perl 11 is currently a philosophy with 3 primary tenets:

Perl 11 promotes ideas which will make Perl 5 pluggable at the following levels:

This will open up the doors to many kinds of language / technology experimentation, without endangering the existing Perl 5 / CPAN code bases that we depend on every day.

Pluggable VMs would be parrot, p2, JVM or .NET running Perl5 and Perl 6 code. 5 + 6 == 11!

Perl 11 Projects

The following projects are important in reaching the vision of Perl 11:

RPerl

A Restricted Perl by Will Braswell which translates a medium-magic subset of Perl 5 into C/C++ using Inline::C and Inline::CPP

cperl

cperl is an improved variant of perl5, running all of perl5 and CPAN code. With many perl6 features, just faster.
Faster than perl5 and perl6. It is stable and usable, but still in development with many more features being added soon.

... ... ...

Perl 11 Links

[Sep 02, 2019] How to get the current line number of a file open using Perl

Sep 02, 2019 | stackoverflow.com

How to get the current line number of a file open using Perl? Ask Question Asked 8 years, 3 months ago Active 6 months ago Viewed 33k times 25 1


tadmc ,May 8, 2011 at 17:08

open my $fp, '<', $file or die $!;

while (<$fp>) {
    my $line = $_;
    if ($line =~ /$regex/) {
        # How do I find out which line number this match happened at?
    }
}

close $fp;

tchrist ,Apr 22, 2015 at 21:16

Use $. (see perldoc perlvar ).

tchrist ,May 7, 2011 at 16:48

You can also do it through OO interface:
use IO::Handle;
# later on ...
my $n = $fp->input_line_number();

This is in perldoc perlvar , too.

> ,

Don't use $. , nor $_ or any global variable. Use this instead:
while(my $line = <FILE>) {
  print $line unless ${\*FILE}->input_line_number == 1;
}

To avoid this and a lot of others Perl gotchas you can use on Atom or VSCode packages like linter-perl . Stop making Perl a write-only language !

[Aug 28, 2019] LogProgramInfo A Perl module to collect and log data for bioinformatics pipelines

Aug 28, 2019 | nlm.nih.gov
Find articles by John M. Macdonald Paul C. Boutros

Informatics and Biocomputing Program, Ontario Institute for Cancer Research, Suite 510, MaRS Centre, 661 University Ave, Toronto, Ontario Canada

Departments of Medical Biophysics and Pharmacology & Toxicology, University of Toronto, Toronto, Ontario Canada

Find articles by Paul C. Boutros Author information Article notes Copyright and License information Disclaimer Informatics and Biocomputing Program, Ontario Institute for Cancer Research, Suite 510, MaRS Centre, 661 University Ave, Toronto, Ontario Canada Departments of Medical Biophysics and Pharmacology & Toxicology, University of Toronto, Toronto, Ontario Canada John M. Macdonald, Email: ac.no.rcio@dlanodcam.nhoj . Contributor Information . corresponding author Corresponding author. # Contributed equally. Received 2015 Nov 26; Accepted 2016 Jun 1. Copyright © The Author(s) 2016

Open Access This article is distributed under the terms of the Creative Commons Attribution 4.0 International License ( http://creativecommons.org/licenses/by/4.0/ ), which permits unrestricted use, distribution, and reproduction in any medium, provided you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license, and indicate if changes were made. The Creative Commons Public Domain Dedication waiver ( http://creativecommons.org/publicdomain/zero/1.0/ ) applies to the data made available in this article, unless otherwise stated. Go to:

Abstract Background

To reproduce and report a bioinformatics analysis, it is important to be able to determine the environment in which a program was run. It can also be valuable when trying to debug why different executions are giving unexpectedly different results.

Results

Log::ProgramInfo is a Perl module that writes a log file at the termination of execution of the enclosing program, to document useful execution characteristics. This log file can be used to re-create the environment in order to reproduce an earlier execution. It can also be used to compare the environments of two executions to determine whether there were any differences that might affect (or explain) their operation.

Availability

The source is available on CPAN (Macdonald and Boutros, Log-ProgramInfo. http://search.cpan.org/~boutroslb/Log-ProgramInfo/ ).

Conclusion

Using Log::ProgramInfo in programs creating result data for publishable research, and including the Log::ProgramInfo output log as part of the publication of that research is a valuable method to assist others to duplicate the programming environment as a precursor to validating and/or extending that research. Keywords: Reproducibility, Log, Environment Go to: Background

Reproducibility is a major concern in science as a whole, and computational biology in particular. For reproducibility, it is not sufficient to provide access to the raw data -- it is ever more critical to also provide access to the program code used to analyse those data [ 2 ]. But the program code is a dynamic mixture of program text, command line arguments, libraries, and various other environmental aspects -- all of which may need to be exactly reproduced to achieve the same results. So, simply providing access to the code used is not a complete solution. It is necessary, but not sufficient.

The need for reproducibility is growing because our pipelines are getting increasingly complex: a typical sequencing pipeline might involve a chain of a dozen unique tools [ 3 ]. But reproducing these pipelines is fundamentally very difficult, in part because it requires duplicating the versions of all dependent tools and libraries used in an analysis. Given the rapid rate of release of updates to common tools (e.g. BWA had 7 updates during the course of 2014 [ 4 ], this can be a significant challenge.

Among the best practices for scientific computing (e.g. [ 5 ]) is listed the need to collect and publish:

A large fraction of pipelines for bioinformatics are written in the Perl programming language (e.g. BioPerl [ 6 ]). However, for logging the precise state of a program at run-time, and capturing all the dependency versions and other key information, there are no automated choices available.

To resolve this issue, we introduce here the module Log::ProgramInfo to facilitate run-time logging of Perl-based pipelines, thereby directly improving the reproducibility of modern bioinformatic analyses.

A further advantage to such tracking information is the ability to test an analsis using later versions of the component tools to determine whether they provide different results (possibly more accurate if the later releases provide better resolution; possibly identifying erroneous results in the original analysis if the tools have been updated with critical fixes to their operation). Go to:

Related work

A search found some programs for related processes but nothing that served the same purposes.

There are some programs available to collect and document the computing process - by recording the steps invoved, including command lines and arguments during the actual data processing. Such a program could work well together with the described module but addresses a different aspect of the reproducibility issue. In our lab, when the workflow of the data analysis was sufficiently complex to require such a description, we instead write a program to encapsulate that process, so there is no long list of manual processing steps to document.

In particular, the program (ReproZip) [ 7 ] was capable of discovering and bundling together all of the programs used during the execution of a process. That seems to have different trade-offs. Such a bundle is only useful on similar hardware and it provides no possibility for assisting with script library version info, or in allowing a later run to use selected variations on the programming environment (such as allowing updated versions of programs that still have the same function but have had security problems fixed). Go to: Implementation

The Log::ProgramInfo module Macdonald and Boutros, Log-ProgramInfo. http://search.cpan.org/~boutroslb/Log-ProgramInfo/ is available as open source, and has been distributed on CPAN (the Comprehansive Perl Archive Network - used as the standard distribution mechanism for the vast majority of open source Perl modules, and described in the Perl documentation with the command "perldoc perlmodinstall").

Log::ProgramInfo is enabled simply by being included with a Perl use statement. Since its effect is global to the program, it should be enabled directly from the main program, or from a utility module that contains global configuration settings for a suite of programs.

Any desired setting of non-default values for the options can be provided either through environment variables, or as "import" list options.

When the module is used for the first time, the loading process carries out a number of actions for its operation:

Every time the Log::ProgramInfo module is used, the import list is processed and any values in it are used to update the option values. (The first time it is used, this processing happens after the initialization steps described above.)

That permits a common group of option settings be processed first, and then specific exceptions to that list over-ridden.

Any option settings provided in environent variables will over-ride the corresponding setting (whether a default or specified by the program import lists). This allows changing the option settings for individual runs so that the log can be suppressed, enabled, or redirected for a single run of the program.

The code that prints the log information ensures that it only executes once (in case multiple signals, or a signal during program termination, would cause it to be called additional times).

If the main body of the program changes a signal handler after Log::ProgramInfo has set it up, that will usually not interfere with Log::ProgramInfo. Usually, the program will catch signals and handle them in a way that allows it continue to operate, or to terminate with an exception. It is only if the program resets a signal handler to its default (abort without normal termination processing) that Log::ProgramInfo's log will not be written. That is not a problem for publication - if the program is being killed by some signal then it is not yet running successfully, and thus not yet ready for publication. However, it does mean that the log might not be available as a diagnostic aid in such situations.

For most cases, that is the only interaction between the program and Log::ProgramInfo.

The one additional interaction that might occur is if there is information unique to the program that is desired to be logged. The function

Log::ProgramInfo::add_extra_logger can be called by the program to specify a callable function that will write additional information to the log. (See the program documentation for precise details.) Go to: Results and discussion

Parameters are available to control the logging process: whether (and if so, where) a log is to be written. Choosing the location where the log is written allows collecting and managing this important information in a way that co-ordinates with the entire set of computational activity carried out for a research project (or an entire organisation's collection of research projects). The default name used for the log file includes the name of the program that is being reported upon as well as a time-stamp to distinguish separate runs -- you might choose to override the name or directory path to provide more complete organisation of logged results. Suppressing log output can be useful for runs that are not intended to generate reproducible results, such as while the software is being developed. However, even in such cases, it might turn out to be useful to have this log output to assist diagnosing problems with system configuration changes -- to confirm that the environment being used is the one that was intended and that updates have actually occurred, etc.

There is an additional parameter that permits the logged information to be sent to a separate logging mechanism, such as a Log4Perl log. This would allow the information to be collected with the other logged information from the program. The output to such logs is mixed with the other logged output from the program, and is also usually reformatted to some extent. Such logs cannot be processed by the Log::ProgramInfo parser provided with the package; hence the normal action for Log::ProgramInfo is to still write its own log file as well. Go to: Log output

The output created by Log::ProgramInfo contains the following information:

The format of the log file is designed to be easily parsed. A parsing subroutine is provided in the package. You could call that subroutine from a program that analyses logs according to your needs. See the program documentation for details. If you have written the log info using a logging module such as Log4Perl, you will have to separately extract the bare ProgramInfo log information out of that log, separating it from any other logging by the program, and removing any line decorations added by the log module. Go to: Example

Here is an example of using Log::ProgramInfo. Assume a simple program, called simple.pl.

An external file that holds a picture, illustration, etc. Object name is 13029_2016_55_Figa_HTML.gif Open in a separate window

When you run it, you get two lines of output.

An external file that holds a picture, illustration, etc. Object name is 13029_2016_55_Figb_HTML.gif Open in a separate window

The first line is the expected output from the program, the second line comes from Log::ProgramInfo to tell you that a log file was created, and where.

Now, take a look at the log file:

An external file that holds a picture, illustration, etc. Object name is 13029_2016_55_Figc_HTML.gif Open in a separate window

Now that you have a log file, you still have to make use of it. Typically, you would treat this log file as one of the output files of your processing activities. So, if you normally discard the output files (e.g. for a test run while developing the pipeline), you will likely also discard the log. On the other hand, for significant runs, you would collect the log file along with the other output files, labelling and storing them as appropriate for reference. The log file would be available as a synopsis of how the output data was created, ready to be used for publication, or reproducing the process (either to validate the results, or to apply the same process to additional data for subsequent research). Go to: Limitations

The C environment is not well built for program introspection activities such as determining which static and/or dynamic libraries have been linked into the program's executable image. This module lists the version of libc that was build into the perl binary - but that information can be out of date. A future release may try to get info about other libraries beyond libc.

Another major problem is that even if a perl module is downloaded from CPAN (which would be one way of ensuring that other people could get the same version), the install process that puts it into the library path for perl programs can be done in may ways, and often is not even done on the same computer as the one that is running the perl program. So, it is not easy to do any sort of detailed validation - the downloaded package bundle is not accessible in any determinable way (and possibly not at all) to the program itself (and thus to Log::ProgramInfo). While it would be possible to compute checksums for every library module that has been loaded, that would take a significant amount of time and is not currently being done. It may be added as an option that could request it explicitly. Go to: Conclusion

Module Log::ProgramInfo provides a convenient way of logging information about the way a program is run. Adding it to existing programs is as easy as adding one line to the program or any module the program already includes.

Log::ProgramInfo's output file can be easily included in the published results along with the actual source code (or references to where it can be found). With this log output, other researchers have information necessary to any meaningful attempt to reproduce the original research, either in the process of validating or extending that research.

Log::ProgramInfo is a good candidate for inclusion in modules intended to mandate standards, and may find use well beyond the field of bioinformatics. Go to: Availability and requirements

Go to: Acknowledgements

Special thanks to Julie Livingstone and Renasha Small-O'Connor for editorial assistance. Go to: Footnotes

cc Bug Reports To: BoutrosLabSoftware@oicr.on.ca

Funding

This study was conducted with the support of the Ontario Institute for Cancer Research to PCB through funding provided by the Government of Ontario. This work was supported by Prostate Cancer Canada and is proudly funded by the Movember Foundation – Grant #RS2014-01. Dr. Boutros was supported by a Terry Fox Research Institute New Investigator Award and a CIHR New Investigator Award. This project was supported by Genome Canada through a Large-Scale Applied Project contract to PCB, Dr. Sohrab Shah and Dr. Ryan Morin.

Authors' contributions

The module was written by the authors. Both authors read and approved the final manuscript.

Competing interests

The authors declare that they have no competing interests.

Go to: Contributor Information

John M. Macdonald, Email: ac.no.rcio@dlanodcam.nhoj .

Paul C. Boutros, Email: ac.no.rcio@sortuob.luap . Go to: References 1. Macdonald J, Boutros P. Log-ProgramInfo. module available from CPAN. http://search.cpan.org/~boutroslb/Log-ProgramInfo/ . 2. Nature-editorial. Code share. Nature. 2014;514. doi:10.1038/514536a. 3. Ewing A, Houlahan K, Hu Y, Ellrott K, Caloian C, Yamaguchi T, Bare J, P'ng C, Waggott D, Sabelnykova V, ICGC-TCGA DREAM Somatic Mutation Calling Challenge participants. Kellen M, Norman T, Haussler D, Friend S, Stolovitzky G, Margolin A, Stuart J, Boutros P. Combining accurate tumour genome simulation with crowd-sourcing to benchmark somatic single nucleotide variant detection. Nat Methods. 2015; 514 :623–30. doi: 10.1038/nmeth.3407. [ PMC free article ] [ PubMed ] [ CrossRef ] [ Google Scholar ] 4. sourceforge-BWA-files. Sourceforge File Listing for BWA on 30 Apr 2015. hand counted from web page. http://sourceforge.net/projects/bio-bwa/files/ . 5. Wilson G, Aruliah DA, Brown CT, Hong NPC, Davis M, Guy RT, Haddock SHD, Huff KD, Mitchell IM, Plumbley MD, Waugh B, White EP, Wilson P. Best practices for scientific computing. PLoS Biol. 2014;12(1). doi:10.1371/journal.pbio.1001745. [ PMC free article ] [ PubMed ] 6. Stajich J, Block D, Boulez K, Brenner SE, Dagdigian C, Fuellen G, Gilbert JGR, Korf I, Lapp H, Lehväslaiho H, Matsalla C, Mungall CJ, Osborne BI, Popock MR, Schattner P, Senger M, Stein L, Stupka E, Wilkinson MD, Birney E. The bioperl toolkit: Perl modules for the life sciences. Genome Res. 2002; 12 (10):1611–8. doi: 10.1101/gr.361602. [ PMC free article ] [ PubMed ] [ CrossRef ] [ Google Scholar ] 7. Chirigati F, Shasha D, Freire J. Presented as Part of the 5th USENIX Workshop on the Theory and Practice of Provenance. Berkeley: USENIX; 2013. Reprozip: Using provenance to support computational reproducibility. [ Google Scholar ]


Articles from Source Code for Biology and Medicine are provided here courtesy of BioMed Central

[Aug 28, 2019] Echo Command in Linux with Examples

Notable quotes:
"... The -e parameter is used for the interpretation of backslashes ..."
"... The -n option is used for omitting trailing newline. ..."
Aug 28, 2019 | linoxide.com

The -e parameter is used for the interpretation of backslashes

... ... ...

To create a new line after each word in a string use the -e operator with the \n option as shown
$ echo -e "Linux \nis \nan \nopensource \noperating \nsystem"

... ... ...

Omit echoing trailing newline

The -n option is used for omitting trailing newline. This is shown in the example below

$ echo -n "Linux is an opensource operating system"

Sample Output

Linux is an opensource operating systemjames@buster:/$

[Aug 27, 2019] How do I get the filename and line number in Perl - Stack Overflow

Aug 27, 2019 | stackoverflow.com

How do I get the filename and line number in Perl? Ask Question Asked 8 years, 10 months ago Active 8 years, 9 months ago Viewed 6k times 6


Elijah ,Nov 1, 2010 at 17:35

I would like to get the current filename and line number within a Perl script. How do I do this?

For example, in a file call test.pl :

my $foo = 'bar';
print 'Hello World';
print functionForFilename() . ':' . functionForLineNo();

It would output:

Hello World
test.pl:3

tchrist ,Nov 2, 2010 at 19:13

These are available with the __LINE__ and __FILE__ tokens, as documented in perldoc perldata under "Special Literals":

The special literals __FILE__, __LINE__, and __PACKAGE__ represent the current filename, line number, and package name at that point in your program. They may be used only as separate tokens; they will not be interpolated into strings. If there is no current package (due to an empty package; directive), __PACKAGE__ is the undefined value.

Eric Strom ,Nov 1, 2010 at 17:41

The caller function will do what you are looking for:
sub print_info {
   my ($package, $filename, $line) = caller;
   ...
}

print_info(); # prints info about this line

This will get the information from where the sub is called, which is probably what you are looking for. The __FILE__ and __LINE__ directives only apply to where they are written, so you can not encapsulate their effect in a subroutine. (unless you wanted a sub that only prints info about where it is defined)

,

You can use:
print __FILE__. " " . __LINE__;

[Aug 26, 2019] Static and state variables in Perl

Aug 26, 2019 | perlmaven.com

In most of the cases we either want a variable to be accessible only from inside a small scope, inside a function or even inside a loop. These variables get created when we enter the function (or the scope created by a a block) and destroyed when we leave the scope.

In some cases, especially when we don't want to pay attention to our code, we want variables to be global, to be accessible from anywhere in our script and be destroyed only when the script ends. In General having such global variables is not a good practice.

In some cases we want a variable to stay alive between function calls, but still to be private to that function. We want it to retain its value between calls.

Are you serious about Perl? Check out my Beginner Perl Maven book .
I have written it for you!

In the C programming language one can designate a variable to be a static variable . This means it gets initialized only once and it sticks around retaining its old value between function calls.

In Perl, the same can be achieved using the state variable which is available starting from version 5.10, but there is a construct that will work in every version of Perl 5. In a way it is even more powerful.

Let's create a counter as an example:

state variable
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub count {
  5. state $counter = 0 ;
  6. $counter ++;
  7. return $counter ;
  8. }
  9. say count ();
  10. say count ();
  11. say count ();
  12. #say $counter;

In this example, instead of using my to declare the internal variable , we used the state keyword.

$counter is initialized to 0 only once, the first time we call counter() . In subsequent calls, the line state $counter = 0; does not get executed and $counter has the same value as it had when we left the function the last time.

Thus the output will be:

1
2
3

If we removed the # from last line, it would generate a Global symbol "$counter" requires explicit package name at ... line ... error when trying to compile the script. This just shows that the variable $counter is not accessible outside the function.

state is executed in the first call

Check out this strange example:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub count {
  5. state $counter = say "world" ;
  6. $counter ++;
  7. return $counter ;
  8. }
  9. say "hello" ;
  10. say count ();
  11. say count ();
  12. say count ();

This will print out

hello
world
2
3
4

showing that the state $counter = say "world"; line only gets executed once. In the first call to count() say , which was also added in version 5.10 , will return 1 upon success.

static variables in the "traditional" way
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my $counter = 0 ;
  6. sub count {
  7. $counter ++;
  8. return $counter ;
  9. }
  10. }
  11. say count ();
  12. say count ();
  13. say count ();

This provides the same result as the above version using state , except that this could work in older versions of perl as well. (Especially if I did not want to use the say keyword, that was also introduced in 5.10.)

This version works because functions declarations are global in perl - so count() is accessible in the main body of the script even though it was declared inside a block. On the other hand the variable $counter is not accessible from the outside world because it was declared inside the block. Lastly, but probably most importantly, it does not get destroyed when we leave the count() function (or when the execution is outside the block), because the existing count() function still references it.

Thus $count is effectively a static variable.

First assignment time
  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. say "hi" ;
  5. {
  6. my $counter = say "world" ;
  7. sub count {
  8. $counter ++;
  9. return $counter ;
  10. }
  11. }
  12. say "hello" ;
  13. say count ();
  14. say count ();
  15. say count ();
hi
world
hello
2
3
4

This shows that in this case too, the declaration and the initial assignment my $counter = say "world"; happens only once, but we can also see that the assignment happens before the first call to count() as if the my $counter = say "world"; statement was part of the control flow of the code outside of the block.

Shared static variable

This "traditional" or "home made" static variable has an extra feature. Because it does not belong to the the count() subroutine, but to the block surrounding it, we can declare more than one functions in that block and we can share this static variable between two or even more functions.

For example we could add a reset_counter() function:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my $counter = 0 ;
  6. sub count {
  7. $counter ++;
  8. return $counter ;
  9. }
  10. sub reset_counter {
  11. $counter = 0 ;
  12. }
  13. }
  14. say count ();
  15. say count ();
  16. say count ();
  17. reset_counter ();
  18. say count ();
  19. say count ();
1
2
3
1
2

Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.

Static arrays and hashes

As of now, you cannot use the state declaration in list context. This means you cannot write state @y = (1, 1); . This limitation could be overcome by some extra coding. For example in this implementation of the Fibonacci series, we checked if the array is empty and set the default values:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. sub fib {
  5. state @y ;
  6. @y = ( 1 , 1 ) if not @y ; # workaround initialization
  7. push @y , $y [ 0 ]+ $y [ 1 ];
  8. return shift @y ;
  9. }
  10. say fib ();
  11. say fib ();
  12. say fib ();
  13. say fib ();
  14. say fib ();

Alternatively we could use the "old-style" static variable with the enclosing block.

Here is the example generating the Fibonacci series:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. {
  5. my @y = ( 1 , 1 );
  6. sub fib {
  7. push @y , $y [ 0 ]+ $y [ 1 ];
  8. return shift @y ;
  9. }
  10. }
  11. say fib ();
  12. say fib ();
  13. say fib ();
  14. say fib ();

[Aug 26, 2019] Beginning Perl Programming From Novice to Professional

Aug 26, 2019 | www.amazon.com

Debugger Commands The debugger has many built-in commands. The most common are as follows.

Command

Meaning

!! cmd

Runs the command (cmd) in a separate process (this is typically a shell command)

h

Interactive help

H -num

Prints last "num" commands (excludes single character commands)

l

Lists the next line of code to be executed

n

Steps through a statement (if subroutines are called, executes over the subroutine)

q

Quits the debugger

s

Steps through a statement (if subroutines are called, executes one subroutine statement at a time)

V

Displays all of the variables in package (defaults to main)

[Aug 26, 2019] debugging - How can I debug a Perl script - Stack Overflow

Jun 27, 2014 | stackoverflow.com

Matthew Lock ,Jun 27, 2014 at 1:01

To run your script under perl debugger you should use -d switch:
perl -d script.pl

But perl is flexible. It supply some hooks and you may force debugger to work as you want

So to use different debuggers you may do:

perl -d:DebugHooks::Terminal script.pl
# OR
perl -d:Trepan script.pl

Look these modules here and here

There are several most interesting perl modules that hook into perl debugger internals: Devel::NYTProf , Devel::Cover

And many others

XXX,

If you want to do remote debug (for cgi or if you don't want to mess output with debug command line) use this:

given test:

use v5.14;
say 1;
say 2;
say 3;

Start a listener on whatever host and port on terminal 1 (here localhost:12345):

$ nc -v -l localhost -p 12345

for readline support use rlwrap (you can use on perl -d too):

$ rlwrap nc -v -l localhost -p 12345

And start the test on another terminal (say terminal 2):

$ PERLDB_OPTS="RemotePort=localhost:12345" perl -d test

Input/Output on terminal 1:

Connection from 127.0.0.1:42994

Loading DB routines from perl5db.pl version 1.49
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(test:2): say 1;
  DB<1> n
main::(test:3): say 2;
  DB<1> select $DB::OUT

  DB<2> n
2
main::(test:4): say 3;
  DB<2> n
3
Debugged program terminated.  Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.  
  DB<2>

Output on terminal 2:

1

Note the sentence if you want output on debug terminal

select $DB::OUT

If you are vim user, install this plugin: dbg.vim which provides basic support for perl

[Aug 26, 2019] D>ebugging - How to use the Perl debugger

Aug 26, 2019 | stackoverflow.com
This is like "please can you give me an example how to drive a car" .

I have explained the basic commands that you will use most often. Beyond this you must read the debugger's inline help and reread the perldebug documentation

The debugger will do a lot more than this, but these are the basic commands that you need to know. You should experiment with them and look at the contents of the help text to get more proficient with the Perl debugger

[Mar 20, 2019] How to I print to STDERR only if STDOUT is a different destination?

Mar 14, 2013 | stackoverflow.com

squiguy, Mar 14, 2013 at 19:06

I would like Perl to write to STDERR only if STDOUT is not the same. For example, if both STDOUT and STDERR would redirect output to the Terminal, then I don't want STDERR to be printed.

Consider the following example (outerr.pl):

#!/usr/bin/perl

use strict;
use warnings;

print STDOUT "Hello standard output!\n";
print STDERR "Hello standard error\n" if ($someMagicalFlag);
exit 0

Now consider this (this is what I would like to achieve):

bash $ outerr.pl
Hello standard output!

However, if I redirect out to a file, I'd like to get:

bash $ outerr.pl > /dev/null
Hello standard error

and similary the other way round:

bash $ outerr.pl 2> /dev/null
Hello standard output!

If I re-direct both out/err to the same file, then only stdout should be displayed:

bash $ outerr.pl > foo.txt 2>&1
bash $ cat foo.txt
Hello standard output!

So is there a way to evaluate / determine whether OUT and ERR and are pointing to the same "thing" (descriptor?)?

tchrist ,Mar 15, 2013 at 5:07

On Unix-style systems, you should be able to do:
my @stat_err = stat STDERR;
my @stat_out = stat STDOUT;

my $stderr_is_not_stdout = (($stat_err[0] != $stat_out[0]) ||
                            ($stat_err[1] != $stat_out[1]));

But that won't work on Windows, which doesn't have real inode numbers. It gives both false positives (thinks they're different when they aren't) and false negatives (thinks they're the same when they aren't).

Jim Stewart ,Mar 14, 2013 at 20:59

You can do that (almost) with -t:
-t STDERR

will be true if it is a terminal, and likewise for STDOUT.

This still would not tell you what terminal, and if you redirect to the same file, you may stilll get both.

Hence, if

-t STDERR && ! (-t STDOUT) || -t STDOUT && !(-t STDERR)

or shorter

-t STDOUT ^ -t STDERR  # thanks to @mob

you know you're okay.

EDIT: Solutions for the case that both STDERR and STDOUT are regular files:

Tom Christianson suggested to stat and compare the dev and ino fields. This will work in UNIX, but, as @cjm pointed out, not in Windows.

If you can guarantee that no other program will write to the file, you could do the following both in Windows and UNIX:

  1. check the position the file descriptors for STDOUT and STDERR are at, if they are not equal, you redirected one of them with >> to a nonempty file.
  2. Otherwise, write 42 bytes to file descriptor 2
  3. Seek to the end of file descriptor 1. If it is 42 more than before, chances are high that both are redirected to the same file. If it is unchanged, files are different. If it is changed, but not by 42, someone else is writing there, all bets are off (but then, you're not in Windows, so the stat method will work).

[Feb 21, 2019] perl - How to prompt for input and exit if the user entered an empty string - Stack Overflow

Feb 20, 2019 | stackoverflow.com

NewLearner ,Mar 12, 2012 at 3:22

I'm new to Perl and I'm writing a program where I want to force the user to enter a word. If the user enters an empty string then the program should exit.

This is what I have so far:

print "Enter a word to look up: ";

chomp ($usrword = <STDIN>);

DVK , Nov 19, 2015 at 19:11

You're almost there.
print "Enter a word to look up: ";
my $userword = <STDIN>; # I moved chomp to a new line to make it more readable
chomp $userword; # Get rid of newline character at the end
exit 0 if ($userword eq ""); # If empty string, exit.

Pondy , Jul 6 '16 at 22:11

File output is buffered by default. Since the prompt is so short, it is still sitting in the output buffer. You can disable buffering on STDOUT by adding this line of code before printing...
select((select(STDOUT), $|=1)[0]);

[Jan 29, 2019] New Perl function each is available in Perl 5.14 and later

Jan 29, 2019 | perldoc.perl.org

called on a hash in list context, returns a 2-element list consisting of the key and value for the next element of a hash. In Perl 5.12 and later only, it will also return the index and value for the next element of an array so that you can iterate over it; older Perls consider this a syntax error. When called in scalar context, returns only the key (not the value) in a hash, or the index in an array.

Hash entries are returned in an apparently random order. The actual random order is specific to a given hash; the exact same series of operations on two hashes may result in a different order for each hash. Any insertion into the hash may change the order, as will any deletion, with the exception that the most recent key returned by each or keys may be deleted without changing the order. So long as a given hash is unmodified you may rely on keys , values and each to repeatedly return the same order as each other. See Algorithmic Complexity Attacks in perlsec for details on why hash order is randomized. Aside from the guarantees provided here the exact details of Perl's hash algorithm and the hash traversal order are subject to change in any release of Perl.

After each has returned all entries from the hash or array, the next call to each returns the empty list in list context and undef in scalar context; the next call following that one restarts iteration. Each hash or array has its own internal iterator, accessed by each , keys , and values . The iterator is implicitly reset when each has reached the end as just described; it can be explicitly reset by calling keys or values on the hash or array. If you add or delete a hash's elements while iterating over it, the effect on the iterator is unspecified; for example, entries may be skipped or duplicated--so don't do that. Exception: It is always safe to delete the item most recently returned by each , so the following code works properly:

  1. while ( my ( $key , $value ) = each %hash ) {
  2. print $key , "\n" ;
  3. delete $hash { $key } ; # This is safe
  4. }

Tied hashes may have a different ordering behaviour to perl's hash implementation.

This prints out your environment like the printenv(1) program, but in a different order:

  1. while ( my ( $key , $value ) = each %ENV ) {
  2. print "$key=$value\n" ;
  3. }

Starting with Perl 5.14, an experimental feature allowed each to take a scalar expression. This experiment has been deemed unsuccessful, and was removed as of Perl 5.24.

As of Perl 5.18 you can use a bare each in a while loop, which will set $_ on every iteration.

  1. while ( each %ENV ) {
  2. print "$_=$ENV{$_}\n" ;
  3. }

To avoid confusing would-be users of your code who are running earlier versions of Perl with mysterious syntax errors, put this sort of thing at the top of your file to signal that your code will work only on Perls of a recent vintage:

  1. use 5.012 ; # so keys/values/each work on arrays
  2. use 5.018 ; # so each assigns to $_ in a lone while test

See also keys , values , and sort .

[Jan 17, 2019] How do I launch the default web browser in Perl on any operating system

Jan 17, 2019 | stackoverflow.com

The second hit on "open url" at search.cpan brings up Browser::Open:

use Browser::Open qw( open_browser );

my $url = 'http://www.google.com/';
open_browser($url);

If your OS isn't supported, send a patch or a bug report.

--cjm

More at Stack Overflow More at Stack Overflow

[Jan 10, 2019] linux - How does cat EOF work in bash - Stack Overflow

Notable quotes:
"... The $sql variable now holds the new-line characters too. You can verify with echo -e "$sql" . ..."
"... The print.sh file now contains: ..."
"... The b.txt file contains bar and baz lines. The same output is printed to stdout . ..."
Jan 10, 2019 | stackoverflow.com

How does "cat << EOF" work in bash? Ask Question 454


hasen ,Mar 23, 2010 at 13:57

I needed to write a script to enter multi-line input to a program ( psql ).

After a bit of googling, I found the following syntax works:

cat << EOF | psql ---params
BEGIN;

`pg_dump ----something`

update table .... statement ...;

END;
EOF

This correctly constructs the multi-line string (from BEGIN; to END; , inclusive) and pipes it as an input to psql .

But I have no idea how/why it works, can some one please explain?

I'm referring mainly to cat << EOF , I know > outputs to a file, >> appends to a file, < reads input from file.

What does << exactly do?

And is there a man page for it?

Dennis Williamson ,Mar 23, 2010 at 18:28

That's probably a useless use of cat . Try psql ... << EOF ... See also "here strings". mywiki.wooledge.org/BashGuide/InputAndOutput?#Here_StringsDennis Williamson Mar 23 '10 at 18:28

hasen ,Mar 23, 2010 at 18:54

@Dennis: good point, and thanks for the link! – hasen Mar 23 '10 at 18:54

Alex ,Mar 23, 2015 at 23:31

I'm surprised it works with cat but not with echo. cat should expect a file name as stdin, not a char string. psql << EOF sounds logical, but not othewise. Works with cat but not with echo. Strange behaviour. Any clue about that? – Alex Mar 23 '15 at 23:31

Alex ,Mar 23, 2015 at 23:39

Answering to myself: cat without parameters executes and replicates to the output whatever send via input (stdin), hence using its output to fill the file via >. In fact a file name read as a parameter is not a stdin stream. – Alex Mar 23 '15 at 23:39

The-null-Pointer- ,Jan 1, 2018 at 18:03

@Alex echo just prints it's command line arguments while cat reads stding(when piped to it) or reads a file that corresponds to it's command line args – The-null-Pointer- Jan 1 '18 at 18:03

kennytm ,Mar 23, 2010 at 13:58

This is called heredoc format to provide a string into stdin. See https://en.wikipedia.org/wiki/Here_document#Unix_shells for more details.

From man bash :

Here Documents

This type of redirection instructs the shell to read input from the current source until a line containing only word (with no trailing blanks) is seen.

All of the lines read up to that point are then used as the standard input for a command.

The format of here-documents is:

          <<[-]word
                  here-document
          delimiter

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word . If any characters in word are quoted, the delimiter is the result of quote removal on word , and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence \<newline> is ignored, and \ must be used to quote the characters \ , $ , and ` .

If the redirection operator is <<- , then all leading tab characters are stripped from input lines and the line containing delimiter . This allows here-documents within shell scripts to be indented in a natural fashion.

Xeoncross ,May 26, 2011 at 22:51

I was having the hardest time disabling variable/parameter expansion. All I needed to do was use "double-quotes" and that fixed it! Thanks for the info! – Xeoncross May 26 '11 at 22:51

trkoch ,Nov 10, 2015 at 17:23

Concerning <<- please note that only leading tab characters are stripped -- not soft tab characters. This is one of those rare case when you actually need the tab character. If the rest of your document uses soft tabs, make sure to show invisible characters and (e.g.) copy and paste a tab character. If you do it right, your syntax highlighting should correctly catch the ending delimiter. – trkoch Nov 10 '15 at 17:23

BrDaHa ,Jul 13, 2017 at 19:01

I don't see how this answer is more helpful than the ones below. It merely regurgitates information that can be found in other places (that have likely already been checked) – BrDaHa Jul 13 '17 at 19:01

Vojtech Vitek ,Feb 4, 2014 at 10:28

The cat <<EOF syntax is very useful when working with multi-line text in Bash, eg. when assigning multi-line string to a shell variable, file or a pipe. Examples of cat <<EOF syntax usage in Bash: 1. Assign multi-line string to a shell variable
$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)

The $sql variable now holds the new-line characters too. You can verify with echo -e "$sql" .

2. Pass multi-line string to a file in Bash
$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF

The print.sh file now contains:

#!/bin/bash
echo $PWD
echo /home/user
3. Pass multi-line string to a pipe in Bash
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF

The b.txt file contains bar and baz lines. The same output is printed to stdout .

edelans ,Aug 22, 2014 at 8:48

In your case, "EOF" is known as a "Here Tag". Basically <<Here tells the shell that you are going to enter a multiline string until the "tag" Here . You can name this tag as you want, it's often EOF or STOP .

Some rules about the Here tags:

  1. The tag can be any string, uppercase or lowercase, though most people use uppercase by convention.
  2. The tag will not be considered as a Here tag if there are other words in that line. In this case, it will merely be considered part of the string. The tag should be by itself on a separate line, to be considered a tag.
  3. The tag should have no leading or trailing spaces in that line to be considered a tag. Otherwise it will be considered as part of the string.

example:

$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
>  HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string

oemb1905 ,Feb 22, 2017 at 7:17

this is the best actual answer ... you define both and clearly state the primary purpose of the use instead of related theory ... which is important but not necessary ... thanks - super helpful – oemb1905 Feb 22 '17 at 7:17

The-null-Pointer- ,Jan 1, 2018 at 18:05

@edelans you must add that when <<- is used leading tab will not prevent the tag from being recognized – The-null-Pointer- Jan 1 '18 at 18:05

JawSaw ,Oct 28, 2018 at 13:44

your answer clicked me on "you are going to enter a multiline string" – JawSaw Oct 28 '18 at 13:44

Ciro Santilli 新疆改造中心 六四事件 法轮功 ,Jun 9, 2015 at 9:41

POSIX 7

kennytm quoted man bash , but most of that is also POSIX 7: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 :

The redirection operators "<<" and "<<-" both allow redirection of lines contained in a shell input file, known as a "here-document", to the input of a command.

The here-document shall be treated as a single word that begins after the next and continues until there is a line containing only the delimiter and a , with no characters in between. Then the next here-document starts, if there is one. The format is as follows:

[n]<<word
    here-document
delimiter

where the optional n represents the file descriptor number. If the number is omitted, the here-document refers to standard input (file descriptor 0).

If any character in word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.

If no characters in word are quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion. In this case, the in the input behaves as the inside double-quotes (see Double-Quotes). However, the double-quote character ( '"' ) shall not be treated specially within a here-document, except when the double-quote appears within "$()", "``", or "${}".

If the redirection symbol is "<<-", all leading <tab> characters shall be stripped from input lines and the line containing the trailing delimiter. If more than one "<<" or "<<-" operator is specified on a line, the here-document associated with the first operator shall be supplied first by the application and shall be read first by the shell.

When a here-document is read from a terminal device and the shell is interactive, it shall write the contents of the variable PS2, processed as described in Shell Variables, to standard error before reading each line of input until the delimiter has been recognized.

Examples

Some examples not yet given.

Quotes prevent parameter expansion

Without quotes:

a=0
cat <<EOF
$a
EOF

Output:

0

With quotes:

a=0
cat <<'EOF'
$a
EOF

or (ugly but valid):

a=0
cat <<E"O"F
$a
EOF

Outputs:

$a
Hyphen removes leading tabs

Without hyphen:

cat <<EOF
<tab>a
EOF

where <tab> is a literal tab, and can be inserted with Ctrl + V <tab>

Output:

<tab>a

With hyphen:

cat <<-EOF
<tab>a
<tab>EOF

Output:

a

This exists of course so that you can indent your cat like the surrounding code, which is easier to read and maintain. E.g.:

if true; then
    cat <<-EOF
    a
    EOF
fi

Unfortunately, this does not work for space characters: POSIX favored tab indentation here. Yikes.

David C. Rankin ,Aug 12, 2015 at 7:10

In your last example discussing <<- and <tab>a , it should be noted that the purpose was to allow normal indentation of code within the script while allowing heredoc text presented to the receiving process to begin in column 0. It is a not too commonly seen feature and a bit more context may prevent a good deal of head-scratching... – David C. Rankin Aug 12 '15 at 7:10

Ciro Santilli 新疆改造中心 六四事件 法轮功 ,Aug 12, 2015 at 8:22

@DavidC.Rankin updated to clarify that, thanks. – Ciro Santilli 新疆改造中心 六四事件 法轮功 Aug 12 '15 at 8:22

Jeanmichel Cote ,Sep 23, 2015 at 19:58

How should i escape expension if some of the content in between my EOF tags needs to be expanded and some don't? – Jeanmichel Cote Sep 23 '15 at 19:58

Jeanmichel Cote ,Sep 23, 2015 at 20:00

...just use the backslash in front of the $Jeanmichel Cote Sep 23 '15 at 20:00

Ciro Santilli 新疆改造中心 六四事件 法轮功 ,Sep 23, 2015 at 20:01

@JeanmichelCote I don't see a better option :-) With regular strings you can also consider mixing up quotes like "$a"'$b'"$c" , but there is no analogue here AFAIK. – Ciro Santilli 新疆改造中心 六四事件 法轮功 Sep 23 '15 at 20:01

Andreas Maier ,Feb 13, 2017 at 12:14

Using tee instead of cat

Not exactly as an answer to the original question, but I wanted to share this anyway: I had the need to create a config file in a directory that required root rights.

The following does not work for that case:

$ sudo cat <<EOF >/etc/somedir/foo.conf
# my config file
foo=bar
EOF

because the redirection is handled outside of the sudo context.

I ended up using this instead:

$ sudo tee <<EOF /etc/somedir/foo.conf >/dev/null
# my config file
foo=bar
EOF

user9048395

add a comment ,Jun 6, 2018 at 0:15
This isn't necessarily an answer to the original question, but a sharing of some results from my own testing. This:
<<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

will produce the same file as:

cat <<test > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
test

So, I don't see the point of using the cat command.

> ,Dec 19, 2013 at 21:40

Worth noting that here docs work in bash loops too. This example shows how-to get the column list of table:
export postgres_db_name='my_db'
export table_name='my_table_name'

# start copy 
while read -r c; do test -z "$c" || echo $table_name.$c , ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
SELECT column_name
FROM information_schema.columns
WHERE 1=1
AND table_schema = 'public'
AND table_name   =:'table_name'  ;
EOF
)
# stop copy , now paste straight into the bash shell ...

output: 
my_table_name.guid ,
my_table_name.id ,
my_table_name.level ,
my_table_name.seq ,

or even without the new line

while read -r c; do test -z "$c" || echo $table_name.$c , | perl -ne 
's/\n//gm;print' ; done < <(cat << EOF | psql -t -q -d $postgres_db_name -v table_name="${table_name:-}"
 SELECT column_name
 FROM information_schema.columns
 WHERE 1=1
 AND table_schema = 'public'
 AND table_name   =:'table_name'  ;
 EOF
 )

 # output: daily_issues.guid ,daily_issues.id ,daily_issues.level ,daily_issues.seq ,daily_issues.prio ,daily_issues.weight ,daily_issues.status ,daily_issues.category ,daily_issues.name ,daily_issues.description ,daily_issues.type ,daily_issues.owner

[Dec 23, 2018] Founder of LiveJournal doesn't know the definition of "ennui"

Dec 23, 2018 | hexmode.com

That is all . (Ok, so I realize some of you will need some more information. Brad Fitzpatrick, with Danga and now SixApart, is pretty amazing when it comes to the software he's developed and released to the public . These range from utilities to provide secure backups on hardware you don't own ( brackup ) distributed job schedulers (The Schwartz) and others I've written about . Note for you Perl-bashers that he did much of this in Perl.)

[Sep 21, 2018] Preferred editor or IDE for development work - Red Hat Learning Community

Pycharm supports Perl, althouth this is not advertized.
Sep 21, 2018 | learn.redhat.com

Re: Preferred editor or IDE for development work

I don't do a lot of development work, but while learning Python I've found pycharm to be a robust and helpful IDE. Other than that, I'm old school like Proksch and use vi.

MICHAEL BAKER
SYSTEM ADMINISTRATOR, IT MAIL SERVICES

micjohns

Re: Preferred editor or IDE for development work

Yes, I'm the same as @Proksch. For my development environment at Red Hat, vim is easiest to use as I'm using Linux to pop in and out of files. Otherwise, I've had a lot of great experiences with Visual Studio.

[Sep 10, 2018] Parsing HTML with Perl by A. Sinan Unur

Notable quotes:
"... Editor's note: If you're looking for tips on how to write more efficient, robust, and maintainable Perl code, you'll want to check out Damien Conway's " Modern Perl Best Practices " video. ..."
Feb 06, 2014 | radar.oreilly.com

Efficiently manipulate documents on the Web|

The need to extract interesting bits of an HTML document comes up often enough that by now we have all seen many ways of doing it wrong and some ways of doing it right for some values of "right".

One might think that one of the most fascinating answers on Stackoverflow has put an end to the desire to parse HTML using regular expressions, but time and again such a desire proves too tempting .

Let's say you want to check all the links on a page to identify stale ones, using regular expressions:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 use strict ; use warnings ; use feature 'say' ; my $ re = qr /< as + href = [ "']([^"']+)["' ] / i ; my $ html = do { local $ / ; < DATA > }; # slurp _DATA_ section my @ links = ($ html =~ m { $ re } gx ); say for @ links ; __DATA__ < html >< body > < p >< a href = "http://example.com/" > An Example </ a ></ p > <!-- < a href = "http://invalid.example.com/" > An Example </ a > --> </ body ></ html >

In this self-contained example, I put a small document in the __DATA__ section. This example corresponds to a situation where the maintainer of the page commented out a previously broken link, and replaced it with the correct link.

When run, this script produces the output:

1 2 3 $ . / href . pl http : //example.com/ http : //invalid.example.com/

It is surprisingly easy to fix using HTML::TokeParser::Simple . Just replace the body of the script above with:

1 2 3 4 5 6 7 8 use HTML :: TokeParser :: Simple ; my $ parser = HTML :: TokeParser :: Simple -> new ( handle => * DATA ); while ( my $ anchor = $ parser -> get_tag ( 'a' )) { next unless defined ( my $ href = $ anchor -> get_attr ( 'href' )); say $ href ; }

When run, this script correctly prints:

1 2 $ . / href http : //example.com/

And, it looks like we made it much more readable in the process!

Of course, interesting HTML parsing jobs involve more than just extracting links. While even that task can be made ever-increasingly complex for the regular expression jockey by, say, adding some interesting attributes between the a and the href , code using HTML::TokeParser::Simple would not be affected.

Another specialized HTML parsing module is HTML::TableExtract . In most cases, it makes going through tables on a page a breeze. For example, the State Actions to Address Health Insurance Exchanges contains State Table 2: Snapshot of State Actions and Figures. The contents of this page may change with new developments, so here is a screenshot of the first few lines of the table:

screen-shot-state-actions-table-2

Parsing this table using HTML::TableExtract is straightforward:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 use HTML :: TableExtract ; use Text :: Table ; my $ doc = 'state-actions-to-implement-the-health-benefit.aspx' ; my $ headers = [ 'State' , 'Selected a Plan' ]; my $ table_extract = HTML :: TableExtract -> new ( headers => $ headers ); my $ table_output = Text :: Table -> new (@$ headers ); $ table_extract -> parse_file ($ doc ); my ($ table ) = $ table_extract -> tables ; for my $ row ($ table -> rows ) { clean_up_spaces ($ row ); # not shown for brevity $ table_output -> load ($ row ); } print $ table_output ;

Running this script yields:

1 2 3 4 5 6 7 $ . / te State Selected a Plan Alabama 624 Alaska 53 Arizona 739 Arkansas 250

Note that I did not even have to look at the underlying HTML code at all for this code to work. If it hadn't, I would have had to delve into that mess to find the specific problem, but, in this case, as in many others in my experience, HTML::TableExtract gave me just what I wanted. So long as the substrings I picked continue to match the content, my script will extract the desired columns even if some of the underlying HTML changes.

Both HTML::TokeParser::Simple (based on HTML::PullParser ) and HTML::TableExtract (which subclasses HTML::Parser parse a stream rather than loading the entire document to memory and building a tree. This made them performant enough for whatever I was able to throw at them in the past.

With HTML::TokeParser::Simple , it is also easy to stop processing a file once you have extracted what you need. That helps when you are dealing with thousands of documents, each several megabytes in size where the interesting content is located towards the beginning. With HTML::TablExtract , performance can be improved by switching to less robust table identifiers such as depths and counts. However, in certain pathological conditions I seem to run into a lot, you may need to play with regexes to first extract the exact region of the HTML source that contains the content of interest.

In one case I had to process large sets of HTML files I had to process where each file was about 8 Mb. The interesting table occurred about 3/4 through the HTML source, and it was clearly separated from the rest of the page by <!-- interesting content here --> style comments. In this particular case, slurping each file, extracting the interesting bit, and passing the content to HTML::TableExtract helped. Throw a little Parallel::ForkManager into the mix, and a task that used to take a few hours went down to less than half an hour.

Sometimes, you just need to be able to extract the contents of the third span within the sixth paragraph of the first content div on the right. Especially if you need to extract multiple pieces of information depending on various parts of the document, creating a tree structure will make that task simpler. It may have a huge performance cost, however, depending on the size of the document. Building trees out of the smallest possible HTML fragments can help here.

Once you have the tree structure, you can address each element or sets of elements. XPath is a way of addressing those elements. HTML::TreeBuilder builds a tree representation of HTML documents. HTML::TreeBuilder::XPath adds the ability to locate nodes in that representation using XPath expressions. So, if I wanted to get the table of contents of the same document, I could have used something along the lines of:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use HTML :: TreeBuilder :: XPath ; use Text :: Table ; my $ doc = 'state-actions-to-implement-the-health-benefit.aspx' ; my $ tree = HTML :: TreeBuilder :: XPath -> new ; my $ toc_table = Text :: Table -> new ( 'Entry' , 'Link' ); $ tree -> parse_file ($ doc ); my @ toc = $ tree -> findnodes ( '//table[@id="bookmark"]/tbody/*/*/*//li/a' ); for my $ el ( @ toc ) { $ toc_table -> add ( $ el -> as_trimmed_text , $ el -> attr ( 'href' ), ); } print $ toc_table ;

Mojo::DOM is an excellent module that uses JQuery style selectors to address individual elements. It is extremely helpful when dealing with documents were HTML elements, classes, and ids were used in intelligent ways.

XML::Twig will also work for some HTML documents, but in general, using an XML parser to parse HTML documents found in the wild is perilious. On the other hand, if you do have well-formed documents, or HTML::Tidy can make them nice, XML::Twig is a joy to use. Unfortunately, it is depressingly too common to find documents pretending to be HTML, using a mish-mash of XML and HTML styles, and doing all sorts of things which browsers can accommodate, but XML parsers cannot.

And, if your purpose is just to clean some wild HTML document, use HTML::Tidy . It gives you an interface to the command line utility tidyp . For really convoluted HTML, it sometimes pays to pass through tidyp first before feeding it into one of the higher level modules.

Thanks to others who have built on HTML::Parser , I have never had to write a line of event handler code myself for real work. It is not that they are difficult to write. I do recommend you study the examples bundled with the distribution to see how the underlying machinery works. It is just that the modules others have built on top of and beyond HTML::Parser make life so much easier that I never had to worry much about going to the lowest possible level.

That's a good thing.

Editor's note: If you're looking for tips on how to write more efficient, robust, and maintainable Perl code, you'll want to check out Damien Conway's " Modern Perl Best Practices " video.

[May 28, 2018] Handling Binary Files in Perl

May 28, 2018 | www.devx.com

For some reason, there exists a common misconception that there is no cross-platform, built-in way in Perl to handle binary files. The copy_file code snippet below illustrates that Perl handles such tasks quite well. The trick is to use "binmode" on both the input and output files after opening them. "Binmode" switches files to binary mode, which for the input file means it won't stop reading at the first "end of text file" character (^Z in win/dos); for the output file binmode means it won't translate '\n' (LF) into '\r\n' (CRLF) when printing. In this way the files get copied byte for byte.

sub copy_file {
  my ($srcfile, $destfile) = @_;
  my $buffer;

  open INF, $srcfile
    or die "\nCan't open $srcfile for reading: $!\n";
  open OUTF, ">$destfile"
    or die "\nCan't open $destfile for writing: $!\n";

  binmode INF;
  binmode OUTF;

  while (
    read (INF, $buffer, 65536)  # read in (up to) 64k chunks, write
    and print OUTF $buffer      # exit if read or write fails
  ) {};
  die "Problem copying: $!\n" if $!;

  close OUTF
    or die "Can't close $destfile: $!\n";
  close INF
    or die "Can't close $srcfile: $!\n";
}
Atanas Banov

[May 09, 2018] reading binary files with Perl

May 09, 2018 | www.perlmonks.org

jpk1292000 has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, I'm new to the board and I've been struggling with this problem for some time now. Hope someone can give me some suggestions... I am trying to read a binary file with the following format: The 4-byte integer and (4 byte float) are in the native format of the machine.


*** First record (4 byte integer) - byte size of record (4*N) (f77 header) (4 byte float) .. 
      value 1 (4 byte float) .. value 2 ... (4 byte float) .. value N N = number of grid points in the field (4 byte 
      integer) .. byte size of record (4*N) (f77 trailer) **** Second record (4 byte integer) - byte size of record (4*N) 
      (f77 header) (4 byte float) .. value 1 (4 byte float) .. value 2 ... (4 byte float) .. value N N = number of grid 
      points in the field (4 byte integer) .. byte size of record (4*N) (f77 trailer)

[download]


    The data is meteorological data (temperature in degrees K) on a 614 x 428 grid. I tried coding up a reader for this, 
    but am getting nonsensical results. Here is the code: 


my $out_file = "/dicast2-papp/DICAST/smg_data/" . $gfn . ".bin"; #path
+

 to binary file my $template = "if262792i"; #binary layout (integer 262792 floats 
      in
+

teger) as described in the format documentation 
      above (not sure if th
+

is is correct) my $record_length 
      = 4; #not sure what record_length is supposed to rep
+

resent 
      (number of values in 1st record, or should it be length of var
+

iable 
      [4 bytes]) my (@fields,$record); open (FH, $out_files ) || die "couldn't open $out_files\n"; until (eof(FH)) { my $val_of_read 
      = read (FH, $record, $record_length) == $record_
+

length 
      or die "short read\n"; @fields = unpack ($template, $record); print "field = $fields[0]\n"; }

[download]


    The results I get when I print out the first field are non-sensical (negative numbers, etc). I think the issue is 
    that I'm not properly setting up my template and record length. Also, how do I find out what is "the native format of 
    the machine"?




Replies are listed 'Best First'.


davorg (Chancellor) on Nov 16, 2006 at 15:53 UTC

Re: reading binary files with Perl

You can find out more about how "read" works by reading its documentation .

From there, you'll find out that the third parameter (your $record_length) is the number of bytes to read from the filehandle[1]. As your template is set up to handle all of the data for one record in one go, you'll need to read one record's worth of data. That's 4 * (1 + 262792 + 1) bytes of data. Currently you're reading four bytes, and the template is looking for a lot more.

The documention for unpack says this:

If there are more pack codes or if the repeat count of a field or a group is larger than what the remainder of the input string allows, the result is not well defined: in some cases, the repeat count is decreased, or unpack() will produce null strings or zeroes, or terminate with an error. If the input string is longer than one described by the TEMPLATE, the rest is ignored.

[1] Actually, the number of _characters_ but let's assume single byte characters for the time being.

--
< http://dave.org.uk >

"The first rule of Perl club is you do not talk about Perl club."
-- Chip Salzenberg

ikegami (Pope) on Nov 16, 2006 at 16:04 UTC

Re: reading binary files with Perl

Depending on your OS, another problem is the lack of binmode . Add binmode(FH) after the open so that Perl doesn't mess with the data. Not all OSes require binmode , but it's safe to use binmode on all OSes.

Oh and I'd use l instead of i . i is not guaranteed to be 4 bytes.

jpk1292000 (Initiate) on Nov 16, 2006 at 19:09 UTC

Re^2: reading binary files with Perl


by jpk1292000 (Initiate) on Nov 16, 2006 at 19:09 UTC

BrowserUk (Pope) on Nov 16, 2006 at 16:13 UTC

Re: reading binary files with Perl

Something like this should do it. See the docs and/or ask for anything you do not understand.


#! perl -slw use strict; my @grid; open my $fh, '<:raw', 'the file' or die $!; while( 1 
            ) { my( $recSize, $dummy, $record ); sysread( $fh, $recSize, 4 ) or last; $recSize = unpack 'N', $recSize; 
            ##(*) sysread( $fh, $record, $recSize ) == $recSize or die "truncated record"; sysread( $fh, $dummy, 4 ) == 4 
            and unpack( 'N', $dummy ) == $recSize ##(*) or die "missing or invalid trailer"; ## (*) You may need V 
            depending upon which platform your file was
+

created 
            on push @grid, [ unpack 'N*', $record ]; } close $fh; ## @grid should now contain your data ## Addressable in 
            the usual $grid[ X ][ Y ] manner. ## Though it might be $array[ Y ][ X ] ## I forget which order FORTRAN 
            writes arrays in?

[download]



Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error. Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal? "Science is about questioning the status quo. Questioning authority". In the absence of evidence, opinion is indistinguishable from prejudice.

ikegami (Pope) on Nov 16, 2006 at 16:29 UTC

Re^2: reading binary files with Perl


by ikegami (Pope) on Nov 16, 2006 at 16:29 UTC

BrowserUk (Pope) on Nov 16, 2006 at 19:17 UTC

Re^3: reading binary files with Perl

ikegami (Pope) on Nov 16, 2006 at 21:12 UTC

Re^4: reading binary files with Perl

jmcnamara (Monsignor) on Nov 16, 2006 at 16:33 UTC

Re: reading binary files with Perl


Try something like the following:


#!/usr/bin/perl -w use strict; open FILE, 'file.bin' or die "Couldn't open file: $!\n"; 
            binmode FILE; my $record = 1; my $buffer = ''; while ( read( FILE, $buffer, 4 ) ) { my $record_length = 
            unpack 'N', $buffer; my $num_fields = $record_length / 4; printf "Record %d. Number of fields = %d\n", 
            $record, $num_fie
+

lds; for (1 .. $num_fields ) { 
            read( FILE, $buffer, 4 ); my $temperature = unpack 'f', $buffer; # Or if the above gives the wrong result try 
            this: #my $temperature = unpack 'f', reverse $buffer; print "\t", $temperature, "\n"; } # Read but ignore 
            record trailer. read( FILE, $buffer, 4 ); print "\n"; $record++; } __END__

[download]


          If the number of fields is wrong subtitute
unpack 'V'
 for
unpack 'N'
. If the float is wrong 
          try the
reverse
ed value that is commented out. 

Update: Added read for trailer.

--
John.

[May 09, 2018] How to read binary file in Perl - Stack Overflow

Notable quotes:
"... BTW: I don't think it's a good idea to read tons of binary files into memory at once. You can search them 1 by 1... ..."
May 09, 2018 | stackoverflow.com

2 down vote favorite 1


Grace ,Jan 19, 2012 at 2:08

I'm having an issue with writing a Perl script to read a binary file.

My code is as the following whereby the $file are files in binary format. I tried to search through the web and apply in my code, tried to print it out, but it seems it doesn't work well.

Currently it only prints the '&&&&&&&&&&&" and ""ppppppppppp", but what I really want is it can print out each of the $line , so that I can do some other post processing later. Also, I'm not quite sure what the $data is as I see it is part of the code from sample in article, stating suppose to be a scalar. I need somebody who can pin point me where the error goes wrong in my code. Below is what I did.

my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir(TEMP1);
closedir(TEMP1);

foreach my $dirs (@dirs) {
    next if ($dirs eq "." || $dirs eq "..");
    print "---->$dirs\n";
    my $d = "$basedir/$key/$dirs";
    if (-d "$d") {
        opendir (TEMP2, $d) || die $!;
        my @files = readdir (TEMP2); # This should read binary files
        closedir (TEMP2);

        #my $buffer = "";
        #opendir (FILE, $d) || die $!;
        #binmode (FILE);
        #my @files =  readdir (FILE, $buffer, 169108570);
        #closedir (FILE);

        foreach my $file (@files) {
            next if ($file eq "." || $file eq "..");
            my $f = "$d/$file";
            print "==>$file\n";
            open FILE, $file || die $!;
            binmode FILE;
            foreach ($line = read (FILE, $data, 169108570)) {
                print "&&&&&&&&&&&$line\n";
                print "ppppppppppp$data\n";
            }
            close FILE;
        }
    }
}

I have altered my code so that it goes like as below. Now I can read the $data. Thanks J-16 SDiZ for pointing out that. I'm trying to push the info I got from the binary file to an array called "@array", thinkking to grep data from the array for string whichever match "p04" but fail. Can someone point out where is the error?

my $tmp = "$basedir/$key";
opendir (TEMP1, "$tmp");
my @dirs = readdir (TEMP1);
closedir (TEMP1);

foreach my $dirs (@dirs) {
    next if ($dirs eq "." || $dirs eq "..");
    print "---->$dirs\n";
    my $d = "$basedir/$key/$dirs";
    if (-d "$d") {
        opendir (TEMP2, $d) || die $!;
        my @files = readdir (TEMP2); #This should read binary files
        closedir (TEMP2);

        foreach my $file (@files) {
            next if ($file eq "." || $file eq "..");
            my $f = "$d/$file";
            print "==>$file\n";
            open FILE, $file || die $!;
            binmode FILE;
            foreach ($line = read (FILE, $data, 169108570)) {
                print "&&&&&&&&&&&$line\n";
                print "ppppppppppp$data\n";
                push @array, $data;
            }
            close FILE;
        }
    }
}

foreach $item (@array) {
    #print "==>$item<==\n"; # It prints out content of binary file without the ==> and <== if I uncomment this.. weird!
    if ($item =~ /p04(.*)/) {
        print "=>$item<===============\n"; # It prints "=><===============" according to the number of binary file I have.  This is wrong that I aspect it to print the content of each binary file instead :(
        next if ($item !~ /^w+/);
        open (LOG, ">log") or die $!;
        #print LOG $item;
        close LOG;
    }
}

Again, I changed my code as following, but it still doesn't work as it do not able to grep the "p04" correctly by checking on the "log" file. It did grep the whole file including binary like this "@^@^@^@^G^D^@^@^@^^@p04bbhi06^@^^@^@^@^@^@^@^@^@hh^R^@^@^@^^@^@^@p04lohhj09^@^@^@^^@@" . What I'm aspecting is it do grep the anything with p04 only such as grepping p04bbhi06 and p04lohhj09. Here is how my code goes:-

foreach my $file (@files) {
    next if ($file eq "." || $file eq "..");
    my $f = "$d/$file";
    print "==>$file\n";
    open FILE, $f || die $!;
    binmode FILE;
    my @lines = <FILE>;
    close FILE;
    foreach $cell (@lines) {
        if ($cell =~ /b12/) {
            push @array, $cell;
        }
    }
}

#my @matches = grep /p04/, @lines;
#foreach $item (@matches) {
foreach $item (@array) {
    #print "-->$item<--";
    open (LOG, ">log") or die $!;
    print LOG $item;
    close LOG;
}

Brad Gilbert ,Jan 19, 2012 at 15:53

use autodie Brad Gilbert Jan 19 '12 at 15:53

reinierpost ,Jan 30, 2012 at 13:00

There is no such thing as 'binary format'. Please be more precise. What format are the files in? What characteristics do they have that cause you to call them 'in binary format'? – reinierpost Jan 30 '12 at 13:00

Grace ,Jan 31, 2012 at 6:56

It is in .gds format. This file is able to read in Unix with strings command. It was reaable in my Perl script but I am not able to grep the data I wanted (p04* here in my code) . – Grace Jan 31 '12 at 6:56

mivk ,Nov 19, 2013 at 13:16

As already suggested, use File::Find or something to get your list of files. For the rest, what do you really want? Output the whole file content if you found a match? Or just the parts that match? And what do you want to match? p04(.*) matches anything from "p04" up to the next newline. You then have that "anything" in $1 . Leave out all the clumsy directory stuff and concentrate first on what you want out of a single file. How big are the files? You are only reading the first 170MB. And you keep overwriting the "log" file, so it only contains the last item from the last file. – mivk Nov 19 '13 at 13:16

jm666 ,May 12, 2015 at 6:44

@reinierpost the OP under the "binary file" probably mean the opposite of the text files - e.g. same thing as is in the perldoc's -X documentation see the -B explanation. (cite: -B File is a "binary" file (opposite of -T).) – jm666 May 12 '15 at 6:44

J-16 SDiZ ,Jan 19, 2012 at 2:19

Use:
$line = read (FILE, $data, 169108570);

The data is in $data ; and $line is the number of bytes read.

       my $f = "$d/$file" ;
       print "==>$file\n" ;
       open FILE, $file || die $! ;

I guess the full path is in $f , but you are opening $file . (In my testing -- even $f is not the full path, but I guess you may have some other glue code...)

If you just want to walk all the files in a directory, try File::DirWalk or File::Find .

Grace ,Jan 19, 2012 at 2:34

Hi J-16 SDiZ, thanks for the reply. each of the $file is in binary format, and what I want to do is to read eaxh of the file to grep some information in readable format and dump into another file (which I consider here as post processing). I want to perform something like "strings <filename> | grep <text synctax>" as in Unix. whereby the <filename> is the $file here in my code. My problem here is cannot read the binary file so that I can proceed with other stuff. Thanks. – Grace Jan 19 '12 at 2:34

Dimanoid ,Jan 20, 2012 at 8:51

I am not sure if I understood you right.

If you need to read a binary file, you can do the same as for a text file:

open F, "/bin/bash";
my $file = do { local $/; <F> };
close F;

Under Windows you may need to add binmode F; under *nix it works without it.

If you need to find which lines in an array contains some word, you can use grep function:

my @matches = grep /something/, @array_to_grep;

You will get all matched lines in the new array @matches .

BTW: I don't think it's a good idea to read tons of binary files into memory at once. You can search them 1 by 1...

If you need to find where the match occurs you can use another standard function, index :

my $offset = index('myword', $file);

Grace ,Jan 30, 2012 at 4:30

Hi Dinanoid, thanks for your answer, I tried it but it didn't work well for me. I tried to edit my code as above (my own code, and it didn't work). Also, tried code as below as you suggested, it didn't work for me either. Can you point out where I did wrong? Thanks. – Grace Jan 30 '12 at 4:30

Peter Mortensen ,May 1, 2016 at 8:31

What will $file be assigned to? An array of characters? A string? Something else? – Peter Mortensen May 1 '16 at 8:31

> ,

I'm not sure I'll be able to answer the OP question exactly, but here are some notes that may be related. (edit: this is the same approach as answer by @Dimanoid, but with more detail)

Say you have a file, which is a mix of ASCII data, and binary. Here is an example in a bash terminal:

$ echo -e "aa aa\x00\x0abb bb" | tee tester.txt
aa aa
bb bb
$ du -b tester.txt 
13  tester.txt
$ hexdump -C tester.txt 
00000000  61 61 20 61 61 00 0a 62  62 20 62 62 0a           |aa aa..bb bb.|
0000000d

Note that byte 00 (specified as \x00 ) is a non-printable character, (and in C , it also means "end of a string") - thereby, its presence makes tester.txt a binary file. The file has size of 13 bytes as seen by du , because of the trailing \n added by the echo (as it can be seen from hexdump ).

Now, let's see what happens when we try to read it with perl 's <> diamond operator (see also What's the use of <> in perl? ):

$ perl -e '
open IN, "<./tester.txt";
binmode(IN);
$data = <IN>; # does this slurp entire file in one go?
close(IN);
print "length is: " . length($data) . "\n";
print "data is: --$data--\n";
'

length is: 7
data is: --aa aa
--

Clearly, the entire file didn't get slurped - it broke at the line end \n (and not at the binary \x00 ). That is because the diamond filehandle <FH> operator is actually shortcut for readline (see Perl Cookbook: Chapter 8, File Contents )

The same link tells that one should undef the input record separator, \$ (which by default is set to \n ), in order to slurp the entire file. You may want to have this change be only local, which is why the braces and local are used instead of undef (see Perl Idioms Explained - my $string = do { local $/; }; ); so we have:

$ perl -e '
open IN, "<./tester.txt";
print "_$/_\n"; # check if $/ is \n
binmode(IN);
{
local $/; # undef $/; is global
$data = <IN>; # this should slurp one go now
};
print "_$/_\n"; # check again if $/ is \n
close(IN);
print "length is: " . length($data) . "\n";
print "data is: --$data--\n";
'

_
_
_
_
length is: 13
data is: --aa aa
bb bb
--

... and now we can see the file is slurped in its entirety.

Since binary data implies unprintable characters, you may want to inspect the actual contents of $data by printing via sprintf or pack / unpack instead.

Hope this helps someone,
Cheers!

[May 04, 2018] bit manipulation - Bit operations in Perl

May 04, 2018 | stackoverflow.com

4 down vote favorite


Toren ,Jan 12, 2011 at 14:50

I have an attribute (32 bits-long), that each bit responsible to specific functionality. Perl script I'm writing should turn on 4th bit, but save previous definitions of other bits.

I use in my program:

Sub BitOperationOnAttr

{

my $a="";

MyGetFunc( $a);

$a |= 0x00000008;

MySetFunc( $a);

}

** MyGetFunc/ MySetFunc my own functions that know read/fix value.

Questions:

  1. if usage of $a |= 0x00000008; is right ?
  2. how extract hex value by Regular Expression from string I have : For example:

"Attribute: Somestring: value (8 long (0x8))"

Michael Carman ,Jan 12, 2011 at 16:13

Your questions are not related; they should be posted separately. That makes it easier for other people with similar questions to find them. – Michael Carman Jan 12 '11 at 16:13

toolic ,Jan 12, 2011 at 16:47

Same question asked on PerlMonks: perlmonks.org/?node_id=881892toolic Jan 12 '11 at 16:47

psmears ,Jan 12, 2011 at 15:00

  1. if usage of $a |= 0x00000008; is right ?

Yes, this is fine.

  1. how extract hex value by Regular Expression from string I have : For example:

"Attribute: Somestring: value (8 long (0x8))"

I'm assuming you have a string like the above, and want to use a regular expression to extract the "0x8". In that case, something like:

if ($string =~ m/0x([0-9a-fA-F]+)/) {
    $value = hex($1);
} else {
    # string didn't match
}

should work.

Toren ,Jan 16, 2011 at 12:35

Thank you for quick answer. You show me the right way to solve the problem – Toren Jan 16 '11 at 12:35

Michael Carman ,Jan 12, 2011 at 16:32

Perl provides several ways for dealing with binary data:

Your scenario sounds like a set of packed flags. The bitwise operators are a good fit for this:

my $mask = 1 << 3;   # 0x0008
$value |=  $mask;    # set bit
$value &= ~$mask;    # clear bit
if ($value & $mask)  # check bit

vec is designed for use with bit vectors. (Each element has the same size, which must be a power of two.) It could work here as well:

vec($value, 3, 1) = 1;  # set bit
vec($value, 3, 1) = 0;  # clear bit
if (vec($value, 3, 1))  # check bit

pack and unpack are better suited for working with things like C structs or endianness.

Toren ,Jan 16, 2011 at 12:36

Thank you . Your answer is very informative – Toren Jan 16 '11 at 12:36

sdaau ,Jul 15, 2014 at 5:01

I upvoted, but there is something very important missing: vec operates on a string! If we use a number; say: $val=5; printf("b%08b",$val); (this gives b00000101 ) -- then one can see that the "check bit" syntax, say: for($ix=7;$ix>=0;$ix--) { print vec($val, $ix, 1); }; print "\n"; will not work (it gives 00110101 , which is not the same number). The correct is to convert the number to ASCII char, i.e. print vec(sprintf("%c", $val), $ix, 1); . – sdaau Jul 15 '14 at 5:01

[Dec 21, 2017] Common Syntax Errors

Dec 21, 2017 | affy.blogspot.com

One very common error is to use elseif instead of the correct elsif keyword. As you program, you'll find that you consistently make certain kinds of errors. This is okay. Everyone has his or her own little quirks. Mine is that I keep using the assignment operator instead of the equality operator. Just remember what your particular blind spot is. When errors occur, check for your personal common errors first.

This section shows some common syntax errors and the error messages that are generated as a result. First, the error message is shown and then the script that generated it. After the script, I'll cast some light as to why that particular message was generated.

Missing semiconon in one of the statements

Scalar found where operator expected at test.pl line 2, near "$bar"
        (Missing semicolon on previous line?)
$foo = { }    # this line is missing a semi-colon.
$bar = 5;
Perl sees the anonymous hash on the first line and is expecting either an operator or the semicolon to follow it. The scalar variable that it finds, $bar , does not fit the syntax of an expression because two variables can't be right after each other. In this case, even though the error message indicates line 2, the problem is in line 1.

Missing quote

Bare word found where operator expected at
    test.pl line 2, near "print("This"
  (Might be a runaway multi-line "" string starting on line 1)
syntax error at test.pl line 2, near "print("This is "
String found where operator expected at test.pl line 3, near "print(""
  (Might be a runaway multi-line "" string starting on line 2)
        (Missing semicolon on previous line?)
Bare word found where operator expected at
    test.pl line 3, near "print("This"
String found where operator expected at test.pl line 3, at end of line
        (Missing operator before ");
?)
Can't find string terminator '"' anywhere before EOF at test.pl line 3.
print("This is a test.\n);    # this line is missing a ending quote.
print("This is a test.\n");
print("This is a test.\n");

In this example, a missing end quote has generated 12 lines of error messages! You really need to look only at the last one in order to find out that the problem is a missing string terminator. While the last error message describes the problem, it does not tell you where the problem is. For that piece of information, you need to look at the first line where it tells you to look at line two. Of course, by this time you already know that if the error message says line 2, the error is probably in line 1.

Unquoted literal

Can't call method "a" in empty package "test" at test.pl line 1.
print(This is a test.\n);    # this line is missing a beginning quote.

The error being generated here is very cryptic and has little to do with the actual problem. In order to understand why the message mentions methods and packages, you need to understand the different, arcane ways you can invoke methods when programming with objects. You probably need to add a beginning quote if you ever see this error message.

... ... ..

This list of syntax errors could go on for quite a while, but you probably understand the basic concepts:

[Dec 20, 2017] chomp - perldoc.perl.org

Notable quotes:
"... Note that parentheses are necessary ..."
Dec 20, 2017 | perldoc.perl.org

chomp Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage

[Dec 20, 2017] Teach Yourself Perl 5 in 21 days - Table of Contents

Dec 20, 2017 | www.davetill.com

Chapter 21 The Perl Debugger


CONTENTS

Today's lesson describes the Perl debugging facility. You'll learn the following:

Entering and Exiting the Perl Debugger

The following sections describe how to start the Perl debugger and how to exit.

Entering the Debugger

To debug a Perl program, specify the -d option when you run the program. For example, to debug a program named debugtest , specify the following command:

$ perl -d debugtest

You can supply other options along with -d if you want to.

When the Perl interpreter sees the -d option, it starts the Perl debugger. The debugger begins by displaying a message similar to the following one on your screen:

Loading DB routines from $RCSfile: perldb.pl,v  $$Revision: 4.0.1.3

$$Date: 92/06/08 13:43:57 $

Emacs support available.



Enter h for help.



main::(debugtest:3):        $dircount = 0;

  DB<1>

The first few lines display the date on which this version of the debugger was created. The only lines of interest are the last two.

The second-to-last line in this display lists the line that the debugger is about to execute. When the debugger starts, the first executable line of the program is displayed.

When the debugger displays a line that it is about to execute, it also provides the following information about the line:

The last line of the display prompts you for a debugging command. The number enclosed in angle brackets indicates the command number; in this case, the number is 1 , because you are about to specify the first debugging command.

Later today you will learn how to use the debugging command number to re-enter debugging commands you have previously executed.

NOTE
To enter the debugger without supplying a program, supply the -e option with the -d option:
$ perl -d -e "1;"
This line starts the debugger with a "program" consisting of the single statement
1;
(which is an expression that doesn't do anything meaningful).
Starting the debugger without a program enables you to examine the predefined system variables or supply statements to be executed. You will learn how to perform both of these tasks later in today's lesson
Exiting the Debugger

To exit the debugger, enter the debugging command q :

DB<1> q

This command halts program execution immediately and returns you to the command shell.

Listing Your Program

You can list any part of your program from within the debugger. The following sections describe debugging commands that perform the display operations.

The command

The simplest way to list part of your program is with the l command, which lists the next few statements in your program:

  DB<1> l

3:      $dircount = 0;

4:      $curdir = "";

5:      while (1) {

6:              # if we don't have a current directory, get one

7:              if ($curdir eq "") {

8:                      print ("Enter directory to list:\n");

9:                      $curdir = <STDIN>;

10:                     $curdir =~ s/^\s+|\s+$//g;

11:                     $curdir = &followlink($curdir);

12:                     &readsubdirs($curdir);

The l command lists a window of executable statements, which is a group of statements small enough to be easily displayed on your screen. A window usually consists of about ten statements. The line number of each statement is displayed at the beginning of its line.

NOTE
The statements displayed in today's lesson are taken from the program presented in "Week 2 in Review."

Entering the l command again displays the window of statements immediately following the last displayed line, which in this example is line 12:

  DB<1> l

13:             }

14:             $curdir = &menudir($curdir);

15:     }

16:

17:

18:     # Find all subdirectories of the given directory,

19:     # and store them in an associative array.

20:     #

21:     # The associative array subscripts and values are:

22:     # <directory name>:       1

You can specify the lines displayed by the l command. If you specify a single line number with the l command, it displays that line:

  DB<1> l 10

10:                      $curdir =~ s/^\s+|\s+$//g;

To display a range of lines, specify the first and last line number, and separate them with a hyphen:

  DB<1> l 10-15

10:                      $curdir =~ s/^\s+|\s+$//g;

11:                      $curdir = &followlink($curdir);

12:                      &readsubdirs($curdir);

13:             }

14:             $curdir = &menudir($curdir);

15:     }

To display a specified number of lines starting at a certain point, supply the starting line number, a + character, and a number of additional lines to display:

  DB<1> l 10+5

10:                      $curdir =~ s/^\s+|\s+$//g;

11:                      $curdir = &followlink($curdir);

12:                      &readsubdirs($curdir);

13:             }

14:             $curdir = &menudir($curdir);

15:     }

You also can use the l command to specify a subroutine to display. To do this, provide the name of the subroutine to display:

  DB<1> l readsubdirs

26:     sub readsubdirs {

27:             local ($dirname) = @_;

28:             local ($dirvar, $subdircount, $name, $index);

29:

30:             # open the current directory;

31:             # $dircount ensures that each file variable is unique

32:             $dirvar = "DIR" . ++$dircount;

33:             if (!opendir ($dirvar, $dirname)) {

34:                     warn ("Can't open $dirname\n");

35:                     return;

This command lists the statements in the subroutine. If the subroutine is too large to fit in a single window, only the first few statements are listed; you can list subsequent statements by entering l with no arguments.

The Command

You can display the lines immediately preceding the last displayed line by entering the - command. For example, the following - command lists the window of lines immediately preceding the subroutine readsubdirs .

  DB<1> -

16:

17:

18:     # Find all subdirectories of the given directory,

19:     # and store them in an associative array.

20:     #

21:     # The associative array subscripts and values are:

22:     # <directory name>:       1

23:     #       (indicates that directory has been read)

24:     # <directory name>.<num>  the <num>th subdirectory

25:

Subsequent - commands go back further in the file.

The Command

To list a window of lines containinga specified line, use the w command, and specify the number of the line to be included:

  DB<1> w 7

4:      $curdir = "";

5:      while (1) {

6:              # if we don't have a current directory, get one

7:              if ($curdir eq "") {

8:                      print ("Enter directory to list:\n");

9:                      $curdir = <STDIN>;

10:                     $curdir =~ s/^\s+|\s+$//g;

11:                     $curdir = &followlink($curdir);

12:                     &readsubdirs($curdir);

13:             }

The w command displays the three lines before the specified line and fills the window with the lines following it.

The // and ?? Commands

You can search for a line containing a particular pattern by enclosing the pattern in slashes:

  DB<1> /Find/

18:     # Find all subdirectories of the given directory,

The debugger searches forward from the last displayed line for a line matching the specified pattern. If it finds such a line, the line is displayed.

To search backward for a particular pattern, enclose the pattern in question marks:

  DB<1> ?readsubdirs?

12:                      &readsubdirs($curdir);

This command starts with the last displayed line and searches backward until it finds a line matching the specified pattern.

NOTE
Patterns specified by // and ?? can contain any special character understood by the Perl interpreter.
You optionally can omit the final / or ? character when you match a pattern.
The Command

The S command lists all the subroutines in the current file, one subroutine per line:

  DB<> S

main::display

main::followlink

main::menudir

main::readsubdirs

Each subroutine name is preceded by the package name and a single quotation mark.

Stepping Through Programs

One of the most useful features of the Perl debugger is the capability to execute a program one statement at a time. The following sections describe the statements that carry out this action.

The Command

To execute a single statement of your program, use the s command:

  DB<2> s

main::(debugtest:4):        $curdir = "";

This command executes one statement of your program and then displays the next statement to be executed. If the statement executed needs to read from the standard input file, the debugger waits until the input is provided before displaying the next line to execute.

TIP
If you have forgotten which line is the next line to execute (because, for example, you have displayed lines using the l command), you can list the next line to execute using the L command:
DB<2> L
3: $dircount = 0;
The L command lists the last lines executed by the program. It also lists any breakpoints and line actions that have been defined for particular lines. Breakpoints and line actions are discussed later today.

If the statement executed by the s command calls a subroutine, the Perl debugger enters the subroutine but does not execute any statements in it. Instead, it stops at the first executable statement in the subroutine and displays it. For example, if the following is the current line:

main::(debugtest:12):                      &readsubdirs($curdir);

specifying the s command tells the Perl debugger to enter readsubdirs and display the following, which is the first executable line of readsubdirs :

main::readsubdirs(debugtest:27):      local ($dirname) = @_;

The s command assumes that you want to debug the subroutine you have entered. If you know that a particular subroutine works properly and you don't want to step through it one statement at a time, use the n command, described in the following section.

The Command

The n command, like the s command, executes one line of your program and displays the next line to be executed:

  DB<2> n

main::(debugtest:5):        while (1) {

The n statement, however, does not enter any subroutines. If the statement executed by n contains a subroutine call, the subroutine is executed in its entirety. After the subroutine is executed, the debugger displays the line immediately following the call.

For example, if the current line is

main::(debugtest:12):                      &readsubdirs($curdir);

the n command tells the debugger to execute readsubdirs and then display the next line in the program, which is

main::(debugtest:13:):             }

Combining the use of s and n ensures that the debugger examines only the subroutines you want to see.

NOTE
The Perl debugger does not enable you to enter any library functions. You can enter only subroutines that you have created yourself or that have been created previously and added to a subroutine library
The command

The f command tells the Perl debugger to execute the remainder of the statements in the current subroutine and then display the line immediately after the subroutine call. This is useful when you are looking for a bug and have determined that the current subroutine does not contain the problem.

The Carriage-Return Command

If you are stepping through a program using s or n , you can save yourself some typing by just pressing Enter when you want to execute another statement. When you press Enter, the debugger repeats the last s or n command executed.

For example, to step from line 5 to line 7, you can use the s command as usual:

  DB<3> s

main::(debugtest:7):              if ($curdir eq "") {

(Line 6 is skipped because it contains no executable statements.) To execute line 7, you can now just press Enter:

  DB<2>

main::(debugtest:8):              print ("Enter directory to list:\n");



NOTE
Pressing Enter has no effect if you have not specified any s or n commands.
The Command

If you are inside a subroutine and decide that you no longer need to step through it, you can tell the Perl debugger to finish executing the subroutine and return to the statement after the subroutine call. To do this, use the r command:

  DB<4> r

main::(debugtest:13:):             }

The statement displayed by the debugger is the first statement following the call to the subroutine.

Displaying Variable Values

Another powerful feature of the Perl debugger is the capability to display the value of any variable at any time. The following sections describe the commands that perform this action.

The Command

The X command displays variables in the current package (which is main if no other package has been specified). If the X command is specified by itself, it lists all the variables in the current package, including the system-defined variables and the variables used by the Perl interpreter itself. Usually, you won't want to use the X command by itself, because there are a lot of system-defined and internal variables known to the Perl interpreter.

To print the value of a particular variable or variables, specify the variable name or names with the X command:

  DB<5> X dircount

$dircount = '0'

This capability often is useful when you are checking for errors in your program.

You must not supply the $ character with the variable name when you use the X command. If you supply the $ character (or the @ or % characters for arrays), the debugger displays nothing.

You can use X to display the values of array variables and associative array variables.

  DB<6> X regarray

@regarray = (

  0     14

  1     'hello'

  2     36

)

  DB<7> X assocarray

%assoc_array = (

  'hi'  1

  'there' 2

)

Each command prints the subscripts of the array and their values. Regular arrays are printed in order of subscript; associative arrays are printed in no particular order.

NOTE
If you have an array variable and a scalar variable with the same name, the X command prints both variables:
DB<8> X var
$var = '0'
@var = (
0 'test1'
1 'test2'
)
There is no way to use X to display one variable but not the other.
The Command

The V command is identical to the X command except that it prints the values of variables in any package. If you specify just a package name, as in the following, this command displays the values of all variables in the package (including system-defined and internal variables):

DB<9> V mypack

If you specify a package name and one or more variable names, as in the following, the debugger prints the values of the variables (if they are defined in that package):

  DB<10> V main dircount

$dircount = '0'

Breakpoints

As you have seen, you can tell the Perl debugger to execute one statement at a time. Another way of controlling program execution is to tell the debugger to execute up to a certain specified point in the program, called a breakpoint .

The following sections describe the commands that create breakpoints, and the command that executes until a breakpoint is detected.

The Command

To set a breakpoint in your program, use the b command. This command tells the debugger to halt program execution whenever it is about to execute the specified line. For example, the following command tells the debugger to halt when it is about to execute line 10:

DB<11> b 10

(If the line is not breakable, the debugger will return Line 10 is not breakable .)

NOTE
You can have as many breakpoints in your program as you want. The debugger will halt program execution if it is about to execute any of the statements at which a breakpoint has been defined.

The b command also accepts subroutine names:

DB<12> b menudir

This sets a breakpoint at the first executable statement of the subroutine menudir .

You can use the b command to tell the program to halt only when a specified condition is true. For example, the following command tells the debugger to halt if it is about to execute line 10 and the variable $curdir is equal to the null string:

DB<12> b 10 ($curdir eq "")

The condition specified with the b statement can be any legal Perl conditional expression.

If a statement is longer than a single line, you can set a breakpoint only at the first line of the statement:
71: print ("Test",
72: " here is more output");
Here, you can set a breakpoint at line 71, but not line 72.
The Command

After you have set a breakpoint, you can tell the debugger to execute until it reaches either the breakpoint or the end of the program. To do this, use the c command:

  DB<13> c

main::(debugtest:10):                  $curdir =~ s/^\s+|\s+$//g;

  DB<14>

When the debugger detects that it is about to execute line 10-the line at which the breakpoint was set-it halts and displays the line. (Recall that the debugger always displays the line it is about to execute.)

The debugger now prompts you for another debugging command. This action enables you to start executing one statement at a time using n or s , continue execution using c , set more breakpoints using b , or perform any other debugging operation.

You can specify a temporary (one-time-only) breakpoint with the c command by supplying a line number:

  DB<15> c 12

main::(debugtest:12):                      &readsubdirs($curdir);

The argument 12 supplied with the c command tells the debugger to define a temporary breakpoint at line 12 and then resume execution. When the debugger reaches line 12, it halts execution, displays the line, and deletes the breakpoint. (The line itself still exists, of course.)

Using c to define a temporary breakpoint is useful if you want to skip a few lines without wasting your time executing the program one statement at a time. Using c also means that you don't have to bother defining a breakpoint using b and deleting it using d (described in the following section).

TIP
If you intend to define breakpoints using c or b , it is a good idea to ensure that each line of your program contains at most one statement. If you are in the habit of writing lines that contain more than one statement, such as
$x++; $y++;
you won't get as much use out of the debugger, because it can't stop in the middle of a line
The Command and Breakpoints

To list all of your breakpoints, use the L command. This command lists the last few lines executed, the current line, the breakpoints you have defined, and the conditions under which the breakpoints go into effect.

  DB<16> L

3:      $dircount = 0;

4:      $curdir = "";

5:      while (1) {

7:              if ($curdir eq "") {

10:                      $curdir =~ s/^\s+|\s+$//g;

  break if (1)

Here, the program has executed lines 3-7, and a breakpoint is defined for line 10. (Line 6 is not listed because it is a comment.) You can distinguish breakpoints from executed lines by looking for the breakpoint conditional expression, which immediately follows the breakpoint. Here, the conditional expression is (1) , which indicates that the breakpoint is always in effect.

The and Commands

When you are finished with a breakpoint, you can delete it using the d command.

DB<16> d 10

This command tells the debugger to delete the breakpoint at line 10. The line itself remains in the program.

If you do not specify a breakpoint to delete, the debugger assumes that a breakpoint is defined for the next line to be executed, and deletes it.

main::(debugtest:12):                      &readsubdirs($curdir);

  DB<17> d

Here, line 12 is the next line to be executed, so the debugger deletes the breakpoint at line 12.

To delete all your breakpoints, use the D command.

DB<18> D

This command deletes all the breakpoints you have defined with the b command.

Tracing Program Execution

When you run a program using the Perl debugger, you can tell it to display each line as it is executed. When the debugger is doing this, it is said to be in trace mode .

To turn on trace mode, use the T command.

  DB<18> t

Trace = on

When a statement is executed in trace mode, the statement is displayed. For example, if the current line is line 5 and the command c 10 (which executes up to line 10) is entered, the following is displayed:

  DB<18> c 10

main::(debugtest:5):      while (1) {

main::(debugtest:7):              if ($curdir eq "") {

main::(debugtest:10):                      $curdir =~ s/^\s+|\s+$//g;

  DB<19>

The debugger prints and executes line 5 and line 7, then displays line 10 and waits for further instructions.

To turn off trace mode, specify the t command again.

  DB<19> t

Trace = off

At this point, trace mode is turned off until another t command is entered.

Line Actions

The Perl debugger enables you to specify one or more statements to be executed whenever the program reaches a specified line. Such statements are known as line actions. The most common line actions are printing the value of a variable and resetting a variable containing an erroneous value to the value you want.

The following sections describe the debugging commands that define line actions.

The Command

To specify a line action for a particular line, use the a command.

DB<19> a 10 print ("curdir is $curdir\n");

This command tells the debugger to execute the statement

print ("curdir is $curdir\n");

whenever it is about to execute line 10 of the program. The debugger performs the action just after it displays the current line and before it asks for the next debugging command.

To create a line action containing more than one statement, just string the statements together. If you need more than one line for the statements, put a backslash at the end of the first line.

  DB<20> a 10 print ("curdir is $curdir\n"); print \

("this is a long line action\n");

In this case, when the debugger reaches line 10, it executes the following statements:

print ("curdir is $curdir\n");

print ("this is a long line action\n");

The Command

To delete the line actions defined using the a command, use the A command.

DB<21> A

This command deletes all line actions currently defined.

NOTE
The A command does not affect the < and > commands, described in the following section.
The < and > Commands

To define a line action that is to be executed before the debugger executes any further statements, use the > command.

DB<21> > print ("curdir before execution is $curdir\n");

This command tells the debugger to print the value of $curdir before continuing.

Similarly, the < command defines a line action that is to be performed after the debugger has finished executing statements and before it asks for another debugging command:

DB<22> < print ("curdir after execution is $curdir\n");

This command tells the debugger to print the value of $curdir before halting execution again.

The < and > commands are useful when you know that one of your variables has the wrong value, but you don't know which statement assigned the wrong value to the variable. By single-stepping through the program using s or n , and printing the variable either before or after executing each statement, you can determine where the variable was given its incorrect value.

NOTE
To delete a line action defined by the < command, enter another < command with no line action defined.
DB<23> <
Similarly, the following command undoes the effects of a > command:
DB<24> >
Displaying Line Actions Using the Command

The L command prints any line actions you have defined using the a command (as well as breakpoints and executed lines). For example, suppose that you have defined a line action using the following command:

DB<25> a 10 print ("curdir is $curdir\n");

The L command then displays this line action as shown here:

main::(debugtest:10):                      $curdir =~ s/^\s+|\s+$//g;

  action:  print ("curdir is $curdir\n");

The line action is always displayed immediately after the line for which it is defined. This method of display enables you to distinguish lines containing line actions from other lines displayed by the L command.

Other Debugging Commands

The following sections describe the debugging commands not previously covered.

Executing Other Perl Statements

In the debugger, anything that is not a debugging command is assumed to be a Perl statement and is performed right away. For example:

DB<4> @array = (1, 2, 3);

You can use statements such as this to alter values in your program as it is being executed. This capability is useful when you are testing your code.

NOTE
If you wish, you can omit the semicolon at the end of the statement.
The Command: Listing Preceding Commands

The H (for "history") command lists the preceding few commands you have entered.

  DB<4> H

3: b 7

2: b 14

1: b 13

The commands are listed in reverse order, with the most recently executed command listed first. Each command is preceded by its command number, which is used by the ! command (described in the following section).

NOTE
The debugger saves only the commands that actually affect the debugging environment. Commands such as l and s , which perform useful work but do not change how the debugger behaves, are not listed by the H command.
This is not a significant limitation because you can enter the letter again if needed.
The Command: Executing Previous Commands

Each command that is saved by the debugger and can be listed by the H command has a command number. You can use this command number to repeat a previously executed command. For example, to repeat command number 5, make the following entry:

  DB <11> !5

b 8

  DB <12>

The debugger displays command number 5-in this case, the command b 8 - and then executes it.

If you omit the number, the debugger repeats the last command executed.

  DB <12> $foo += $bar + 1

  DB <13> !

$foo += $bar + 1

  DB <14>

If you specify a negative number with ! , the debugger skips back that many commands:

  DB <14> $foo += $bar + 1

  DB <15> $foo *= 2

  DB <16> ! -2

$foo += $bar + 1

  DB <17>

Here, the ! -2 command refers to the command $foo += $bar + 1 .

You can use ! only to repeat commands that are actually repeatable. Use the H command to list the commands that the debugger has saved and that can be repeated
The Command: Stack Tracing

The T command enables you to display a stack trace, which is a collection of all the subroutines that have been called, listed in reverse order. Here is an example:

  DB <16> T

$ = &main::sub2('hi') from file debug1 line 7

$ = &main::sub1('hi') from file debug1 line 3

Here, the T command indicates that the program is currently inside subroutine sub2 , which was called from line 7 of your program; this subroutine is part of the main package. The call to sub2 is passed the argument 'hi' .

The $ = preceding the subroutine name indicates that the subroutine call is expecting a scalar return value. If the call is expecting a list to be returned, the characters @ = appear in front of the subroutine name.

The next line of the displayed output tells you that sub2 was called by another subroutine, sub1 . This subroutine was also passed the argument 'hi' , and it was called by line 3 of the program. Because the stack trace lists no more subroutines, line 3 is part of your main program.

NOTE
The list of arguments passed to a subroutine that is displayed by the stack trace is the list of actual values after variable substitution and expression evaluation are performed. This procedure enables you to use the stack trace to check whether your subroutines are being passed the values you expect.
The Command: Printing an Expression

An easy way to print the value of an expression from inside the debugger is to use the p command.

  DB <17> p $curdir + 1

1

The p command evaluates the expression and displays the result.

NOTE
The p command writes to the screen even when the program has redirected STDOUT to a file.
The Command: Defining Aliases

If you find yourself repeatedly entering a long debugging command and you want to save yourself some typing, you can define an alias for the long command by using the = command. For example:

  DB <15> = pc print ("curdir is $curdir\n");

= pc print ("curdir is $curdir\n");

The = command prints the alias you have just defined and then stores it in the associative array %DB'alias (package DB , array name alias ) for future reference. From here on, the command

DB <16> pc

is equivalent to the command

DB <16> print ("curdir is $curdir\n");

To list the aliases you have defined so far, enter the = command by itself:

  DB <17> =

pc =  print ("curdir is $curdir\n")

This command displays your defined aliases and their equivalent values.

Predefining Aliases

You can define aliases that are to be created every time you enter the Perl debugger.

When the debugger starts, it first searches for a file named .perldb in your home directory. If the debugger finds this file, it executes the statements contained there.

To create an alias, add it to the .perldb file. For example, to add the alias

= pc print ("curdir is $curdir\n");

add the following statement to your .perldb file:

$DB'alias{"pc"} = 's/^pc/print ("curdir is $curdir\n");/';

Here's how this works: when the Perl debugger creates an alias, it adds an element to the $DB'alias associative array. The subscript for this element is the alias you are defining, and the value is a substitution command that replaces the alias with the actual command you want to use. In the preceding example, the substitution takes any command starting with pc and replaces it with

print ("curdir is $curdir\n");


Be careful when you define aliases in this way. For example, your substitution should match only the beginning of a command, as in /^pc/ . Otherwise, the alias will replace any occurrence of the letters pc with your print command, which is not what you want.
The Command: Debugger Help

The h (for help) command provides a list of each of the debugger commands listed in today's lesson, along with a one-line explanation of each. This is handy if you are in the middle of debugging a program and forget the syntax of a particular command.

Summary

Today, you have learned about the Perl debugger. This debugger enables you to perform the following tasks, among others:

Q&A
Q: Is it possible to enter more than one debugging command at a time?
A: No; however, there's no real need to do so. If you want to perform several single steps at once, use the c command to skip ahead to a specified point. If you want to both step ahead and print the value of a variable, use the < or > command.
Q: Is it possible to examine variables in one package while inside another?
A: Yes. Use the V command or the standard Perl package/variable syntax.
Q: If I discover that my program works and I want to turn off debugging, what do I do?
A: You cannot exit the debugger in the middle of a program. However, if you delete all breakpoints and line actions and then enter the c command, the program begins executing normally and is no longer under control of the debugger.
Q: How can I convert to a reusable breakpoint a one-time breakpoint created using c ?
A: By default, the b command sets a breakpoint at the line that is about to be executed. This is the line at which c has set its one-time breakpoint.
Q: How can I execute other UNIX commands from inside the debugger?
A: Enter a statement containing a call to the Perl system function. For example, to display the contents of the current directory, enter the following command:
DB <11> system ("ls");
To temporarily escape from the debugger to a UNIX shell, enter the following command:
DB <12> system ("sh");
When you are finished with the shell, enter the command exit, and you will return to the debugger.
Q: What special built-in variables can be accessed from inside the debugger?
A: All of them.
Workshop

The Workshop provides quiz questions to help you solidify your understanding of the material covered.

Quiz
  1. Define the following terms:
    1. trace mode
    2. stack trace
    3. breakpoint
    4. line action
  1. Explain the differences between the X and V commands.
  2. Explain the differences between the // and ?? commands.
  3. Explain the differences between the < and > commands.
  4. Explain the differences between the s and n commands.
  5. What do the following commands do?
    1. l
    2. l 26
    3. l 5-7
    4. l 5+7
    5. w


[Dec 20, 2017] debugging - Can the Perl debugger save the ReadLine history to a file

Dec 20, 2017 | stackoverflow.com
The way I do this is by having the following line in my ~/.perldb file:

&parse_options("HistFile=$ENV{HOME}/.perldb.hist");

Debugger commands are then stored in ~/.perldb.hist and accessible across sessions.

I did the following:

1) Created ~/.perldb , which did not exist previously.

2) Added &parse_options("HistFile=$ENV{HOME}/.perldb.hist"); from mirod's answer.

3) Added export PERLDB_OPTS=HistFile=$HOME/.perldb.history to ~/.bashrc from mephinet's answer.

4) Ran source .bashrc

5) Ran perl -d my program.pl , and got this warning/error

perldb: Must not source insecure rcfile /home/ics/.perldb.
        You or the superuser must be the owner, and it must not 
        be writable by anyone but its owner.

6) I protected ~/.perldb with owner rw chmod 700 ~/.perldb , and the error went away.

[Dec 20, 2017] The Perl Debugger

Dec 20, 2017 | nnc3.com

Subroutines

There is one more variation of the list code command, l . It is the ability to list the code of a subroutine, by typing l sub , where sub is the subroutine name.

Running the code in Listing 2 returns:

Loading DB routines from perl5db.pl version 1
Emacs support available.
Enter h or h h for help.
main::(./p2.pl:3): require 5.001;
 DB<1>

Entering l searchdir allows us to see the text of searchdir , which is the meat of this program.

22 sub searchdir { # takes directory as argument
23: my($dir) = @_;
24: my(@files, @subdirs);
25
26: opendir(DIR,$dir) or die "Can't open \"
27:     $dir\" for reading: $!\n";
28
29: while(defined($_ = readdir(DIR))) {
30: /^\./ and next; # if file begins with '.', skip
31
32 ### SUBTLE HINT ###
As you can see, I left a subtle hint. The bug is that I deleted an important line at this point.

Setting Breakpoints

If we were to step through every line of code in a subroutine that is supposed to be recursive, it would take all day. As I mentioned before, the code as in Listing 2 seems only to list the files in the current directory, and it ignores the files in any subdirectories. Since the code only prints the files in the current, initial directory, maybe the recursive calls aren't working. Invoke the Listing 2 code under the debugger.

Now, set a breakpoint. A breakpoint is a way to tell the debugger that we want normal execution of the program until it gets to a specific point in the code. To specify where the debugger should stop, we insert a breakpoint. In the Perl debugger, there there are two basic ways to insert a breakpoint. The first is by line number, with the syntax b linenum . If linenum is omitted, the breakpoint is inserted at the next line about to be executed. However, we can also specify breakpoints by subroutine, by typing b sub , where sub is the subroutine name. Both forms of breakpointing take an optional second argument, a Perl conditional. If when the flow of execution reached the breakpoint the conditional evaluates to true, the debugger will stop at the breakpoint; otherwise, it will continue. This gives greater control of execution.

For now we'll set a break at the searchdir subroutine with b searchdir . Once the breakpoint is set, we'll just execute until we hit the subroutine. To do this, enter c (for continue). Adding Actions

Looking at the code in Listing 2, we can see that the first call to searchdir comes in the main code. This seems to works fine, or else nothing would be printed out. Press c again to continue to the next invocation of searchdir , which occurs in the searchdir routine.

We wish to know what is in the $dir variable, which represents the directory that will be searched for files and subdirectories. Specifically, we want to know the contents of this variable each time we cycle through the code. We can do this by setting an action. By looking at the program listing, we see that by line 25, the variable $dir has been assigned. So, set an action at line 25 in this way:

a 25 print "dir is $dir\n"

Now, whenever line 25 comes around, the print command will be executed. Note that for the a command, the line number is optional and defaults to the next line to be executed.

Pressing c will execute the code until we come across a breakpoint, executing action points that are set along the way. In our example, pressing c continuously will yield the following:

main::(../p2.pl:3): require 5.001;
 DB<1> b searchdir
 DB<2> a 25 print "dir is $dir\n"
 DB<3> c
main::searchdir(../p2.pl:23): my($dir) = @_;
 DB<3> c
dir is .
main::searchdir(../p2.pl:23): my($dir) = @_;
 DB<3> c
dir is dir1.0
main::searchdir(../p2.pl:23): my($dir) = @_;
 DB<3> c
dir is dir2.0
main::searchdir(../p2.pl:23): my($dir) = @_;
 DB<3> c
dir is dir3.0
file1
file1
file1
file1
DB::fake::(/usr/lib/perl5/perl5db.pl:2043):
2043: "Debugged program terminated. Use `q' to quit or `R' to
restart.";
 DB<3>

Note that older versions of the debugger don't output the last line as listed here, but instead exit the debugger. This newer version is nice because when the program has finished it still lets you have control so that you can restart the program.

It still seems that we aren't getting into any subdirectories. Enter D and A to clear all breakpoints and actions, respectively, and enter R to restart. Or, in older debugger versions, simply restart the program to begin again.

We now know that the searchdir subroutine isn't being called for any subdirectories except the first level ones. Looking back at the text of the program, notice in lines 44 through 46 that the only time the searchdir subroutine is called recursively is when there is something in the @subdirs list. Put an action at line 42 that will print the $dir and @subdirs variables by entering:

a 42 print "in $dir is @subdirs \n"

Now, put a breakpoint at line 12 to prevent the program from outputting to our screen ( b 12 ), then enter c . This will tell us all the subdirectories that our program thinks are in the directory.

main::(../p2.pl:3): require 5.001;
 DB<1> a 42 print "in $dir is @subdirs \n"
 DB<2> b 12
 DB<3> c
in . is dir1.0 dir2.0 dir3.0
in dir1.0 is
in dir2.0 is
in dir3.0 is
main::(../p2.pl:12): foreach (@files) {
 DB<3>
This program sees that there are directories in ".", but not in any of the subdirectories within ".". Since we are printing out the value of @subdirs at line 42, we know that @subdirs has no elements in it. (Notice that when listing line 42, there is the letter "a" after the line number and a colon. This tells us that there is an action point here.) So, nothing is being assigned to @subdirs in line 37, but should be if the current (as held in $_ ) file is a directory. If it is, it should be pushed into the @subdirs list. This is not happening.

One error I've committed (intentionally, of course) is on line 38. There is no catch-all "else" statement. I should probably put an error statement here. Instead of doing this, let's put in another action point. Reinitialize the program so that all points are cleared and enter the following:

a 34 if( ! -f $_ and ! -d $_ ) { print "in $dir: $_ is
weird!\n" }
b 12"
c

which reveals:

main::(../p2.pl:3): require 5.001;
 DB<1> a 34 if( ! -f $_ and ! -d $_ ) { print "in $dir:
$_ is weird!\n" }
 DB<2> b 12
 DB<3> c
in dir1.0: dir1.1 is weird!
in dir1.0: dir2.1 is weird!
in dir1.0: file2 is weird!
in dir1.0: file3 is weird!
in dir2.0: dir2.1 is weird!
in dir2.0: dir1.1 is weird!
in dir2.0: file2 is weird!
in dir2.0: file3 is weird!
main::(../p2.pl:12): foreach (@files) {
 DB<3>
While the program can read (through the readdir call on line 29) that dir1.1 is a file of some type in dir1.0, the file test (the -f construct) on dir1.1 says that it is not.

It would be nice to halt the execution at a point (line 34) where we have a problem. We can use the conditional breakpoint that I mentioned earlier to do this. Reinitialize or restart the debugger, and enter:

b 34 ( ! -f $_ and ! -d $_ )
c
p
p $dir

You'll get output that looks like this:

main::(../p2.pl:3): require 5.001;
 DB<1> b 34 ( ! -f $_ and ! -d $_ )
 DB<2> c
main::searchdir(../p2.pl:34): if( -f $_) { # if its a file...
 DB<2> p
dir1.1
 DB<2> p $dir
dir1.0
 DB<3>
The first line sets the breakpoint, the next c executes the program until the break point stops it. The p prints the contents of the variable $_ and the last command, p $dir prints out $dir . So, dir1.1 is a file in dir1.0, but the file tests ( -d and -f ) don't admit that it exists, and therefore dir1.1 is not being inserted into @subdirs (if it's a directory) or into @files (if it's a file).

Now that we are back at a prompt, we could inspect all sorts of variables, subroutines or any other Perl construct. To save you from banging your heads against your monitors, and thus saving both your heads and your monitors, I'll tell you what is wrong.

All programs have something known as the current working directory (CWD). By default, the CWD is the directory where the program starts. Any and all file accesses (such as file tests or file and directory openings) are made in reference from the CWD. At no time does our program change its CWD. But the values returned by the readdir call on line 29 are simply file names relative to the directory that readdir is reading (which is in $dir ). So, when we do the readdir , $_ gets assigned a string representing a file (or directory) within the directory in $dir (which is why it's called a subdirectory). But when running the -f and -d file tests, they look for $_ in the context of the CWD. But it isn't in the CWD, it's in the directory represented by $dir . The moral of the story is that we should be working with $dir/$_ , not just $_ . So the string

###SUBTLE HINT###

should be replaced by

$_ = "$dir/$_"; # make all path names absolute
That sums it up. Our problem was we were dealing with relative paths, not absolute (from the CWD) paths.

Putting it back into our example, we need to check dir1.0/dir1.1 , not dir1.1 . To check to make sure that this is what we want, we can put in another action point. Try typing:

a 34 $_ = "$dir/$_"
c

In effect this temporarily places the corrective measure into our code. Action points are the first item on the line to be evaluated. You should now see the proper results of the execution of the program:

DB<1> a 34 $_ = "$dir/$_"
DB<2> c
./file1
./dir1.0/file1
./dir1.0/file2
./dir1.0/file3
./dir1.0/dir1.1/file1
./dir1.0/dir1.1/file2
./dir1.0/dir1.1/file3
./dir2.0/file1
./dir2.0/file2
./dir2.0/file3
./dir2.0/dir2.1/file1
./dir2.0/dir2.1/file2
./dir3.0/file1
DB::fake::(/usr/lib/perl5/perl5db.pl:2043):
2043: "Debugged program terminated. Use `q' to quit or `R' to
restart.";
 DB<2>

Stack Traces

Now that we've got the recursive call debugged, let's play with the calling stack a bit. Giving the command T will display the current calling stack. The calling stack is a list of the subroutines which have been called between the current point in execution and the beginning of execution. In other words, if the main portion of the code executes subroutine "a", which in turn executes subroutine "b", which calls "c", then pressing "T" while in the middle of subroutine "c" outputs a list going from "c" all the way back to "main".

Start up the program and enter the following commands (omit the second one if you have fixed the bug we discovered in the last section):

b 34 ( $_ =~ /file2$/)
a 34 $_ = "$dir/$_"
c

These commands set a breakpoint that will only stop execution if the value of the variable $_ ends with the string file2 . Effectively, this code will halt execution at arbitrary points in the program. Press T and you'll get this:

@ = main::searchdir('./dir1.0/file2') called from file '../p2.pl' line
45
@ = main::searchdir(.) called from file '../p2.pl' line 10

Enter c , then T again:

@ = main::searchdir('./dir1.0/dir1.1/file2') called from file
`../p2.pl' line 45
@ = main::searchdir(undef) called from file '../p2.pl' line 45
@ = main::searchdir(.) called from file '../p2.pl' line 10

Do it once more:

@ = main::searchdir('./dir2.0/file2') called from file '../p2.pl' line
45
@ = main::searchdir(.) called from file '../p2.pl' line 10

You can go on, if you so desire, but I think we have enough data from the arbitrary stack dumps we've taken.

We see here which subroutines were called, the debugger's best guess of which arguments were passed to the subroutine and which line of which file the subroutine was called from. Since the lines begin with @ = , we know that searchdir will return a list. If it were going to return a scalar value, we'd see $ = . For hashes (also known as associative arrays), we would see % = .

I say "best guess of what arguments were passed" because in Perl, the arguments to subroutines are placed into the @_ magic list. However, manipulating @_ (or $_ ) in the body of the subroutine is allowed and even encouraged. When a T is entered, the stack trace is printed out, and the current value of @_ is printed as the arguments to the subroutine. So when @_ is changed, the trace doesn't reflect what was actually passed as arguments to the subroutine.

[Dec 20, 2017] Creating Command Aliases

Notable quotes:
"... You use the = command without any arguments when you want a list of the current aliases. ..."
Dec 20, 2017 | affy.blogspot.com

The = command is used to create command aliases. If you find yourself issuing the same long command over and over again, you can create an alias for that command. For example, the debugger command

= pFoo print("foo=$foo\n");
creates an alias called pFoo . After this command is issued, typing pFoo at the debugger prompt produces the same results as typing print("foo=$foo\n"); .

You use the = command without any arguments when you want a list of the current aliases.

If you want to set up some aliases that will always be defined, create a file called .perldb and fill it with your alias definitions. Use the following line as a template:

$DB::alias{'pFoo'} = 'print("foo=$foo\n");';
After you create this file and its alias definitions, the aliases will be available in every debugging session.

[Dec 20, 2017] Perl Debugger Quick Reference Card by Andrew Ford

Notable quotes:
"... in the current and home directories ..."
"... Any input to the debugger that is not recognized is executed as Perl code in the current package. ..."
Dec 20, 2017 | shinnok.com

Revision 0.1 for Perl Debugger version 5.8.x

Copyright: Andrew Ford refcards.com™

... ... ...

Debugger Commands

The debugger reads commands from the files .perldb in the current and home directories, and stops before the first run-time executable statement, displaying the line it is about to execute and a prompt:

DB<1>

If you run code from the debugger and hit another breakpoint, the prompt will look like DB"42". The numbers within the angle brackets are the command numbers, used when repeating commands.

Any input to the debugger that is not recognized is executed as Perl code in the current package.

Prefixing a command with ' | ' pipes the output to your current pager.

Help and Quiting

Debugger Control

... ... ...

[Dec 20, 2017] Chapter 30 -- Using the Perl Debugger

Dec 20, 2017 | ods.com.ua
... ... ... Looking at Values

To see the values of certain variables in the program, use the V command. Used by itself, V lists all the variables in scope at this time. Here's the syntax:

V [ package [ variable ]]

To look at values in your program, you'll want to look at the main package. For example, to print the value of $reply , use this command:

V main reply
$reply = '1'

Note that the dollar sign before the variable specified to V is not supplied. Therefore, if you specify the command V main $reply , you are actually asking for the value of $$reply and not $reply .

The trace option is available with the t toggle command. Issuing trace once turns it on, and issuing it again turns it off. See Figure 30.4 for a sample use of the trace command on Listing 30.2. In this example, trace is turned on, and then the c command is issued to run the debugger continuously. In trace mode, the debugger prints out each line of code that executes.

Figure 30.4 : Using the trace command with breakpoints.

The X command is helpful when displaying values of variables in the current package. Remember that the main package is the default package for a Perl script. Issued by itself with no options, the X command displays all the variables in the current package. Avoid issuing the X command by itself because it can generate a very long listing of all the variables in the main package.

To see the value of a particular variable instead of all the variables, type the name of the variable after the X command. For example, the following command

X fileNumber

will print the value of the fileNumber variable in the current package. If you have array variables and scalar variables with the same name in the same package, the X command will display the values of both these variables. For example, if you have a scalar variable called names and an array called names , the X command will show the values of both variables:

DB<3> X names
$names = "kamran"
@names = (
"kamran"
"joe"
"donald"
)
Breakpoints

You can place breakpoints at suspect locations in your code and run the program until one of the specified breakpoints is hit. Breakpoints can be specified to be hit as soon as the line of code is about to be executed.

The c command is used to step forward until either the program stops or a specified breakpoint is hit. To specify a breakpoint at the current line, use the b command without any parameters. To specify a specific line, use the command of the form:

b linenumber

Usually, you use trace statements to see statements between the current execution point and a breakpoint (refer to Figure 30.4). The program is run in continuous mode with the c command until it hits a breakpoint. There is a breakpoint in Listing 30.1 that causes the debugger to stop. The L command is issued in the example to list the breakpoints in the system.

Breakpoints can also be specified to occur at the first executable line of code within a subroutine. Simply use the b command with the name of the subroutine as the first parameter. For example, to break at the first line of code in the xyc subroutine, try this command:

b xyc

You can also ask the debugger to look at a condition when a line is hit with a breakpoint tag on it. If the breakpoint is specified at a line and the condition is true, the debugger stops; otherwise, it keeps on going. For example, if you want the debugger to stop in xyc only when the global $reply is 1 , use this command:

b xyc ($reply == '1')

To list all breakpoints defined during a debug session, use the L command. If you issue unconditional breakpoints, you'll see breakpoints listed as this:

break if (1)

The L command will also list up to the last five executed lines of the program.

To remove a breakpoint, use the d command and specify the line number to delete. To remove all breakpoints, use the D command. For example, to delete a breakpoint at line 12, you would issue the command d 12 .

The DB package uses the following sequence to hit breakpoints and evaluate code on each line of executable code:

  1. Checks to see whether the breakpoint is defined at this line number. If there is no breakpoint defined for this line, it starts to process the next line. If there is a break-
    point at this line, the debugger prepares to stop. If the condition for the defined breakpoint is true, the debugger stops execution and presents a prompt to the user.
  2. Checks to see whether the line of code is printable. If so, it prints the entire line of code (including code spanning multiple lines).
  3. Checks to see whether there are any actions defined for this line and performs these actions. (An action is a set of Perl commands to be executed.)
  4. Checks to see whether the stop was due to a breakpoint. If the condition for the breakpoint is true and a breakpoint has been marked in this location, the debugger stops and presents a prompt for user interaction.
  5. Evaluates the line and gets ready to execute it. Gets user input if the user is stopping; otherwise, it executes the line and returns to item 1 in order to process the next line.
Actions

You can specify actions to take when a certain line of code is executed. This step is very important when you want to print out values as the program executes (see Figure 30.5). Notice how the value of reply is printed out when line 73 is reached. The action is defined with this statement:

Figure 30.5 : Using actions in the debugger.

a 73 print "I am on line 73 and reply is $reply"

Notice that you did not have to terminate the action command with a semicolon. You need to use semicolons only if you have more than one statement for an action. If you forget to supply the terminating semicolon, the debugger will supply it for you. In any event, try to keep actions simple and short. Don't write lengthy actions unless absolutely necessary; otherwise, you'll slow down the debugger and clutter up the output on your terminal.

Actions are not limited to displaying values. For instance, you can use an action to reset a variable to a known value while in a loop, using a statement like this:

a 73 $reply = 1; print "forced reply to 1\n";

To execute statements within the debugged program's space, simply type the command at the prompt. For example, to explicitly create and set the value of $kw to 2 in the code, use the following commands at the DB<> prompt:

DB<1> $kw = 2
... nothing is printed here ...
DB<1> print $kw
2
DB<1> V main kw
$kw = '2'

In this example, the variable $kw is created and defined in the program environment. You cannot modify the source code in the original program, but you can add items to the name space.

In some cases, your program may have redirected its output to STDOUT and therefore whatever it is printing will not be shown on the console. To evaluate an expression and print its value out to the console regardless of how STDOUT is redirected, you can use the p command. The p command evaluates an expression in the current program's environment and prints it out to the debugger console. Basically, the print command prints the output to wherever STDOUT is redirected, whereas the p command is equivalent to the following print command:

print DB::OUT

The command above forces output from a print command to where the DB:: package prints its output.

Searching for Patterns

To look for certain strings in the source code, you can use the forward slash command followed by the string to look for. Note that there are no spaces between the / and the string you are looking for. The string can be specified between two slashes, but the second slash is optional. Actually, you can search for regular expressions, just as in Perl.

To search forward in the file, use the / operator. To search backward, use the question mark operator ( ? ).

The history of the commands you have executed is tracked in the debugger. Only commands greater than one character long are listed in this directory. To execute commands from the history list, use the bang operator ( ! ) followed by the index of the command. To execute a command from the history, type ! and the index of the command to redo. This should be familiar to Bash and C shell programmers.

To see the current history of commands in the buffer of commands in the debugger, type the H command. For example, in the middle of a debug session, if you type in the H command at the DB<3> prompt, you should expect to see three items listed in reverse order of execution:

DB<3> H
3: b 79
2: w 2
1: w 9
Subroutines

To list all the subroutines currently in the system, use the S command. The output from the S command lists all subroutines in any package that your code uses. For example, if you run the program in Listing 30.2 with the debugger, you will see output as shown in Figure 30.6.

Figure 30.6 : Listing subroutine names.


Listing 30.2. A sample listing.
1 #!/usr/bin/perl -d
2
3 use VRML;
4 use VRML::Cube;
5
6 my $header = VRML::new();
7 $header->VRML::startHeader;
8
9 $header->VRML::startSeparator;
10
11 my $cubeb = $header->VRML::putCube(
12 'width' => 0.5, 'height' => 0.5 , 'depth' => 0.5 ,
13 'translation' => [1,0,0]
14 );
15 my $cubed = $header->VRML::putCube(
16 'width' => 1, 'height' => 1 , 'depth' => 1 ,
17 'translation' => [1,1,0],
18 );
19 $header->VRML::stopSeparator;

At any time in a debug session, you can do a "stack trace," which is a listing of the calling order of the functions called so far. Be aware that if you are modifying the argument stack in any way, the values of the passed arguments might not be correct. The T command will do a stack trace for you.

Caveats

First of all, there is no way to restart the debugger if there is a problem. If you overstep something, you have to start all over. This means getting out of the program and restarting the debugger.

Second, the debugger itself is not completely debugged yet. If you notice certain problems, such as your commands not being recognized, it's probably because you typed too many characters at the prompt.

Table 30.1 lists the information about the available debugger commands. All information in this table is gleaned from the perl5db.pl source file. Keep this table handy so that you don't have to go to the file to see what options are available.

Table 30.1. The commands available from the debugger.
Command Description
a [ ln ] command Sets an action to take before the line is executed.
b Sets an unconditional breakpoint at the current line.
b [ ln ] [ cond ] Sets a breakpoint if the condition is true at the specified line number.
b sname [ cond ] Sets a breakpoint at the first line inside the subroutine sname() .
c Continues until the next breakpoint or until the end of the program.
c line Continues and stops at the specified line.
d [ line ] Deletes the breakpoint at a given line.
D Deletes all breakpoints.
f filename Switches to the filename as the default.
H - number Displays history of all commands longer than one character.
L Lists all breakpoints and actions.
l min+incr Lists incr+1 lines starting at line #min .
l min-max Lists lines from min to max , inclusively.
l line Lists one line of code at a specified line.
l Lists the next 10 lines of code from the last location.
l name Lists a subroutine by name.
n Next code at the same level. Steps over subroutine calls.
p expr Same as print DB::OUT expr in current package.
q or ^D Quits. You cannot use quit .
r Returns from current subroutine.
s Single-step over code. Steps into subroutines.
S Lists all known subroutine names in the current scope.
t Toggles trace mode on and off.
T Performs a stack trace.
V Lists all variables in all used packages.
V pkg List all variables in a given package.
V pkg var Lists all variables in a package that have var in them.
w line Lists five lines before and five lines after current line.
<CR> Repeats last n or s .
- Lists the previous window.
/ regexp / Searches forward for a pattern using a regular expression.
? regexp ? Searches backward for a pattern using a regular expression.
< command Defines the command before the prompt.
> command Defines the command after the prompt.
! number Redoes a command (the default is the previous command).
! - number Redoes number\'th to the last command.
= [ alias value ] Starts a command alias.
= Lists all the current aliases.
command Executes as a Perl statement in the current package.
Customizing Your Debugger Environment

There are ways to customize your debugger environment. If you do not like the one-character commands that come with the debugger, you can use different aliases. There is a hash in the DB:: package called %alias() that contains the command strings. You can substitute your own commands in place of the existing ones using the = command. Since most of the time you'll want to keep your changes consistent between debug sessions, you can edit a file called .perldb in the current working directory and place the assignments there. Here's a sample .perldb file:

$DB::alias{'ln'} = 's/ln/p $1/';
$DB::alias{'z'} = 's/z/l/';

These two lines will substitute the value of p for every command ln you type, and the value of l for every z command. Of course, you'll probably want to alias long commands into short one-character sequences to save yourself some time.

Using the debugger should not be your only method for getting bugs out of the system. The -w switch is important if you want Perl to do checking and warn you of error conditions while executing. The types of messages generated vary from warnings to notifications of fatal errors that can cause the program to abort.

For More Information

Reading the source file perl5db.pl gives you a few clues about how the debugger works and the commands that are available during a debug session. Consult the perldebug.html page at www.metronet.com . This file contains the full list of all the options in the debug environment. Review the perldiag.html page for a list of possible diagnostic values you get from using the w switch.

Summary

Nothing really beats the use of well-placed print statements to do debugging. However, Perl does offer a simple yet powerful debugging tool with the -d option. The interactive debugger lets you step through code, into or over subroutines, set breakpoints, execute commands, and look at variables in a Perl program.

[Dec 19, 2017] Perl IDE and Editor Poll, October 2009 - Which editor(s) or IDE(s) are you using for Perl development

Oct 01, 2009 | perlide.org

In October 2009 we ran a poll asking people Which editor(s) or IDE(s) are you using for Perl development? . The poll was promoted via the blog of Gabor Szabo which is syndicated in several Perl related sites such as the Iron Man Challenge , Perlshpere and Planet Perl . It was also promoted via Twitter , the Perl group in Reddit , the Perl Mongers group in LinkedIn and the Perl Community Adserver to get more people to cast their vote. Request was also sent to the Perl Monger group leaders. Some of them have forwarded the request to their respective groups.

The list of editors was taken from the Perl Development Tools page on Perlmonks and the "randomize answers" checkbox was clicked after filling in the data. No idea if that really randomized the answers. During the poll people could mark other editors and type in the name of and editor. Some of these editors were added to the list of possible answers during the poll. In addition there were people who typed in the name of the editor in the other field even though the name appeared on the list.

At the begining we set the poll to allow multiple choice with up to 3 answers per person but later on we noticed that at one of the updates it became multiple choice unlimited answers. Unfortunatelly the free polling system we used gave details only on the number of answers and not the number of people who answered.

The poll ran between 21-24 October 2009 for about 72 hours. There were 3,234 answers when it was closed.

The results are as follows.
Vim (or vi or gvim) 1097 34%
Emacs (or xemacs, with or without extensions) 430 13%
Ultra Edit (plain or Studio) 224 7%
Eclipse EPIC 210 6%
Other answer... 143 4%
Notepad++ 142 4%
Komodo IDE 128 4%
Komodo Edit 105 3%
TextMate 105 3%
Padre 101 3%
Kate 56 2%
Gedit 55 2%
TextPad 49 2%
nano 40 1%
SciTE 38 1%
Geany 36 1%
NEdit 27 1%
mcedit 26 1%
EditPlus 26 1%
BBEdit 25 1%
JEdit 23 1%
Joe 20 1%
Smultron 16 0%
TextWrangler 14 0%
PSPad 12 0%
Notepad2 12 0%
Open Perl IDE 10 0%
OptiPerl 9 0%
Pico 7 0%
Jed 6 0%
Kephra 6 0%
SlickEdit 6 0%
KDevelop 6 0%
Notepad 5 0%
Crimson 4 0%
Anjuta 3 0%
EngInSite-Perl 3 0%
KEdit 3 0%
Perl Express 2 0%
DzSoft Perl 2 0%
PerlWiz 1 0%
Far 1 0%
Perl Studio 0 0%
Perl Builder 0 0%
Editeur 0 0%
Perl Code Editor 0 0%
ED for Windows 0 0%
PerlEdit 0 0%
FTE 0 0%
visiPerl+ 0 0%
Prof. Notepad 0 0%
Perl Scripting Tool 0 0%

[Dec 19, 2017] Programming in Perl - Debugging

Mar 13, 2007 | cs.rpi.edu

On this page, I will post aides and tools that Perl provides which allow you to more efficently debug your Perl code. I will post updates as we cover material necessary for understanding the tools mentioned.

CGI::Dump
Dump is one of the functions exported in CGI.pm's :standard set. It's functionality is similar to that of Data::Dumper . Rather than pretty-printing a complex data structure, however, this module pretty-prints all of the parameters passed to your CGI script. That is to say that when called, it generates an HTML list of each parameter's name and value, so that you can see exactly what parameters were passed to your script. Don't forget that you must print the return value of this function - it doesn't do any printing on its own.
use CGI qw/:standard/;
print Dump;
Benchmark
As you know by now, one of Perl's mottos is "There's More Than One Way To Do It" (TMTOWTDI ©). This is usually a Good Thing, but can occasionally lead to confusion. One of the most common forms of confusion that Perl's verstaility causes is wondering which of multiple ways one should use to get the job done most quickly.

Analyzing two or more chunks of code to see how they compare time-wise is known as "Benchmarking". Perl provides a standard module that will Benchmark your code for you. It is named, unsurprisingly, Benchmark . Benchmark provides several helpful subroutines, but the most common is called cmpthese() . This subroutine takes two arguments: The number of iterations to run each method, and a hashref containing the code blocks (subroutines) you want to compare, keyed by a label for each block. It will run each subroutine the number of times specified, and then print out statistics telling you how they compare.

For example, my solution to ICA5 contained three different ways of creating a two dimensional array. Which one of these ways is "best"? Let's have Benchmark tell us:

#!/usr/bin/perl
use strict;
use warnings;
use Benchmark 'cmpthese';

sub explicit {
    my @two_d = ([ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ],
                 [ ('x') x 10 ]);
}

sub new_per_loop {
    my @two_d;
    for (0..4){
        my @inner = ('x') x 10;
        push @two_d, \@inner;
    }
}

sub anon_ref_per_loop {
    my @two_d;
    for (0..4){
        push @two_d, [ ('x') x 10 ];
    }
}

sub nested {
    my @two_d;
    for my $i (0..4){
        for my $j (0..9){
            $two_d[$i][$j] = 'x';
        }
    }
}
cmpthese (10_000, {
                 'Explicit'           => \&explicit,
                 'New Array Per Loop' => \&new_per_loop,
                 'Anon. Ref Per Loop' => \&anon_ref_per_loop,
                 'Nested Loops'       => \&nested,
             }
      );
The above code will print out the following statistics (numbers may be slightly off, of course):
Benchmark: timing 10000 iterations of Anon. Ref Per Loop, Explicit, Nested Loops, New Array Per Loop...
Anon. Ref Per Loop:  2 wallclock secs ( 1.53 usr +  0.00 sys =  1.53 CPU) @ 6535.95/s (n=10000)
Explicit:  1 wallclock secs ( 1.24 usr +  0.00 sys =  1.24 CPU) @ 8064.52/s (n=10000)
Nested Loops:  4 wallclock secs ( 4.01 usr +  0.00 sys =  4.01 CPU) @ 2493.77/s (n=10000)
New Array Per Loop:  2 wallclock secs ( 1.76 usr +  0.00 sys =  1.76 CPU) @ 5681.82/s (n=10000)
                     Rate Nested Loops New Array Per Loop Anon. Ref Per Loop Explicit
Nested Loops       2494/s           --               -56%               -62%     -69%
New Array Per Loop 5682/s         128%                 --               -13%     -30%
Anon. Ref Per Loop 6536/s         162%                15%                 --     -19%
Explicit           8065/s         223%                42%                23%       --

The benchmark first tells us how many iterations of which subroutines it's running. It then tells us how long each method took to run the given number of iterations. Finally, it prints out the statistics table, sorted from slowest to fastest. The Rate column tells us how many iterations each subroutine was able to perform per second. The remaining colums tells us how fast each method was in comparison to each of the other methods. (For example, 'Explicit' was 223% faster than 'Nested Loops', while 'New Array Per Loop' is 13% slower than 'Anon. Ref Per Loop'). From the above, we can see that 'Explicit' is by far the fastest of the four methods. It is, however, only 23% faster than 'Ref Per Loop', which requires far less typing and is much more easily maintainable (if your boss suddenly tells you he'd rather have the two-d array be 20x17, and each cell init'ed to 'X' rather than 'x', which of the two would you rather had been used?).

You can, of course, read more about this module, and see its other options, by reading: perldoc Benchmark

Command-line options
Perl provides several command-line options which make it possible to write very quick and very useful "one-liners". For more information on all the options available, refer to perldoc perlrun
-e
This option takes a string and evaluates the Perl code within. This is the primary means of executing a one-liner
perl -e'print qq{Hello World\n};'
(In windows, you may have to use double-quotes rather than single. Either way, it's probably better to use q// and qq// within your one liner, rather than remembering to escape the quotes).
-l
This option has two distinct effects that work in conjunction. First, it sets $\ (the output record terminator) to the current value of $/ (the input record separator). In effect, this means that every print statement will automatically have a newline appended. Secondly, it auto-chomps any input read via the <> operator, saving you the typing necessary to do it.
perl -le 'while (<>){ $_ .= q{testing};  print; }'
The above would automatically chomp $_, and then add the newline back on at the print statement, so that "testing" appears on the same line as the entered string.
-w
This is the standard way to enable warnings in your one liners. This saves you from having to type use warnings;
-M
This option auto- use s a given module.
perl -MData::Dumper -le'my @foo=(1..10); print Dumper(\@foo);'
-n
This disturbingly powerful option wraps your entire one-liner in a while (<>) { ... } loop. That is, your one-liner will be executed once for each line of each file specified on the command line, each time setting $_ to the current line and $. to current line number.
perl -ne 'print if /^\d/' foo.txt beta.txt
The above one-line of code would loop through foo.txt and beta.txt, printing out all the lines that start with a digit. ($_ is assigned via the implicit while (<>) loop, and both print and m// operate on $_ if an explict argument isn't given).
-p
This is essentially the same thing as -n , except that it places a continue { print; } block after the while (<>) { ... } loop in which your code is wrapped. This is useful for reading through a list of files, making some sort of modification, and printing the results.
perl -pe 's/Paul/John/' email.txt
Open the file email.txt, loop through each line, replacing any instance of "Paul" with "John", and print every line (modified or not) to STDOUT
-i
This one sometimes astounds people that such a thing is possible with so little typing. -i is used in conjunction with either -n or -p. It causes the files specified on the command line to be edited "in-place", meaning that while you're looping through the lines of the files, all print statements are directed back to the original files. (That goes for both explicit print s, as well as the print in the continue block added by -p.)
If you give -i a string, this string will be used to create a back-up copy of the original file. Like so:
perl -pi.bkp -e's/Paul/John/' email.txt msg.txt
The above opens email.txt, replaces each line's instance of "Paul" with "John", and prints the results back to email.txt. The original email.txt is saved as email.txt.bkp. The same is then done for msg.txt

Remember that any of the command-line options listed here can also be given at the end of the shebang in non-one-liners. (But please do not start using -w in your real programs - use warnings; is still preferred because of its lexical scope and configurability).

Data::Dumper
The standard Data::Dumper module is very useful for examining exactly what is contained in your data structure (be it hash, array, or object (when we come to them) ). When you use this module, it exports one function, named Dumper . This function takes a reference to a data structure and returns a nicely formatted description of what that structure contains.
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my @foo = (5..10);
#add one element to the end of the array
#do you see the error?
$foo[@foo+1] = 'last';

print Dumper(\@foo);

When run, this program shows you exactly what is inside @foo:

$VAR1 = [
          5,
          6,
          7,
          8,
          9,
          10,
          undef,
          'last'
        ];

(I know we haven't covered references yet. For now, just accept my assertion that you create a reference by prepending the variable name with a backslash...)

__DATA__ & <DATA>
Perl uses the __DATA__ marker as a pseudo-datafile. You can use this marker to write quick tests which would involve finding a file name, opening that file, and reading from that file. If you just want to test a piece of code that requires a file to be read (but don't want to test the actual file opening and reading), place the data that would be in the input file under the __DATA__ marker. You can then read from this pseudo-file using <DATA>, without bothering to open an actual file:
#!/usr/bin/env perl
use strict;
use warnings;

while (my $line = <DATA>) {
  chomp $line;
  print "Size of line $.:  ", length $line, "\n";
}

__DATA__
hello world
42
abcde

The above program would print:

Size of line 1: 11
Size of line 2: 2
Size of line 3: 5
$.
The $. variable keeps track of the line numbers of the file currently being processed via a while (<$fh>) { ... } loop. More explicitly, it is the number of the last line read of the last file read.
__FILE__ & __LINE__
These are two special markers that return, respectively, the name of the file Perl is currently executing, and the Line number where it resides. These can be used in your own debugging statements, to remind yourself where your outputs were in the source code:
  print "On line " . __LINE__ . " of file " . __FILE__ . ", \$foo = $foo\n";
   
   
   
   

Note that neither of these markers are variables, so they cannot be interpolated in a double-quoted string

warn() & die()
These are the most basic of all debugging techniques. warn() takes a list of strings, and prints them to STDERR. If the last element of the list does not end in a newline, warn() will also print the current filename and line number on which the warning occurred. Execution then proceeds as normal.

die() is identical to warn() , with one major exception - the program exits after printing the list of strings.

All debugging statements should make use of either warn() or die() rather than print() . This will insure you see your debugging output even if STDOUT has been redirected, and will give you the helpful clues of exactly where in your code the warning occurred.

[Dec 19, 2017] Open Perl IDE - User Manual

Dec 19, 2017 | open-perl-ide.sourceforge.net

This section explains how to use Open Perl IDE for debugging.

Important: Open Perl IDE is not able to debug any scripts, if it does not know a path to "perl.exe". If the PATH environment variable contains a valid location, then "perl.exe" will be detected automatically. Otherwise it is necessary to enter a valid location into the "Preferences | General | Directories | Path to perl.exe" field.

There are two methods to debug a script:

After execution is stopped, it is possible to analyse the actual state of the script by Furthermore, it is possible to set/delete breakpoints (see section 5.1 Breakpoints) or to continue/abort the execution of the script. The following table shows the different navigation possibilities:

Table: Debug Navigation

Name Shortcut Description
Run F9 Start/Continue script execution until next breakpoint is reached.
Step Over F8 Execute the current script line, not tracing into subroutines.
Step Into F7 Execute the next command in the current script line, tracing into subroutines.
Abort CTRL-F2 Request termination of debug session.
Force Termination CTRL-ALT-F12 Immediately terminate debug session.
You should only use "Force Termination" if you see no other way to stop script execution. Dont't expect Open Perl IDE to work correctly after using forced termination !

If script execution has finished, then Open Perl IDE automatically switches back from debug mode to edit mode.

[Dec 19, 2017] Antibugging in Perl 7 Tips for Reducing Complexity

Notable quotes:
"... The complexity of a program is a function of several factors: ..."
Dec 19, 2017 | www.informit.com

"Complexity is the enemy, and our aim is to kill it." -Jan Baan

One of Perl's greatest strengths is its expressiveness and extreme conciseness. Complexity is the bane of software development: when a program grows beyond a certain size, it becomes much harder to test, maintain, read, or extend. Unfortunately, today's problems mean this is true for every program we need. Anything you can do to minimize the complexity of your program will pay handsome dividends.

The complexity of a program is a function of several factors:

Whenever a language allows you to change some code to reduce any of these factors, you reduce complexity.

3.7.1 Lose the Temporary Variables

The poster child for complexity is the temporary variable. Any time a language intrudes between you and the solution you visualize, it diminishes your ability to implement the solution. All languages do this to some degree; Perl less than most. 13 In most languages, you swap two variables a and b with the following algorithm:

Declare temp to be of the same type as a and b
temp = a;
a = b;
b = temp;

But most languages are not Perl:

($b, $a) = ($a, $b);

Iterating over an array usually requires an index variable and a count of how many things are currently stored in the array:

int i;
for (i = 0; i < count_lines; i++) 
 {
 strcat (line[i], suffix);
 }

Whereas in Perl, you have the foreach construct borrowed from the shell:

foreach my $line (@lines) { $line .= $suffix }

And if you feel put out by having to type foreach instead of just for , you're in luck, because they're synonyms for each other; so just type for if you want (Perl can tell which one you mean).

Because functions can return lists, you no longer need to build special structures just to return multivalued data. Because Perl does reference-counting garbage collection, you can return variables from the subroutine in which they are created and know that they won't be trampled on, yet their storage will be released later when they're no longer in use. And because Perl doesn't have strong typing of scalars, you can fill a hierarchical data structure with heterogeneous values without having to construct a union datatype and some kind of type descriptor.

Because built-in functions take lists of arguments where it makes sense to do that, you can pass them the results of other functions without having to construct an iterative loop:

unlink grep /~$/, readdir DIR;

And the map function lets you form a new list from an old one with no unnecessary temporary variables:

open PASSWD, '/etc/passwd' or die "passwd: $!\n";
my @usernames = map /^([^:]+)/, <PASSWD>;
close PASSWD;

Because Perl's arrays grow and shrink automatically and there are simple operators for inserting, modifying, or deleting array elements, you don't need to build linked lists and worry if you've got the traversal termination conditions right. And because Perl has the hash data type, you can quickly locate a particular chunk of information by key or find out whether a member of a set exists.

3.7.2 Scope Out the Problem

Of course, sometimes temporary variables are unavoidable. Whenever you create one though, be sure and do it in the innermost scope possible (in other words, within the most deeply nested set of braces containing all references to the variable).

Create variables in the innermost scope possible.

For example, let's say somewhere in my program I am traversing my Netscape history file and want to save the URLs visited in the last 10 days in @URLs :

use Netscape::History;
my $history = new Netscape::History;
my (@URLs, $url);
while (defined($url = $history->next_url() )) 
 {
 push @URLs, $url if 
    time - $url->last_visit_time < 10 * 24 * 3600;
 }

This looks quite reasonable on the face of it, but what if later on in our program we create a variable called $history or $url ? We'd get the message

"my" variable $url masks earlier declaration in same scope

which would cause us to search backward in the code to find exactly which one it's referring to. Note the clause " in same scope " -- if in the meantime you created a variable $url at a different scope, well, that may be the one you find when searching backward with a text editor, but it won't be the right one. You may have to check your indentation level to see the scope level.

This process could be time-consuming. And really, the problem is in the earlier code, which created the variables $history or $url with far too wide a scope to begin with. We can (as of perl 5.004) put the my declaration of $url right where it is first used in the while statement and thereby limit its scope to the while block. As for $history , we can wrap a bare block around all the code to limit the scope of those variables:

use Netscape::History;
my @URLs;
 {
 my $history = new Netscape::History;
 while (defined(my $url = $history->next_url() )) 
  {
  push @URLs, $url 
   if time - $url->last_visit_time < 10 * 24 * 3600;
  }
 }

If you want to create a constant value to use in several places, use constant.pm to make sure it can't be overwritten:

$PI = 3.1415926535897932384;

use constant PI => 3.1415926535897932384;

my $volume = 4/3 * PI * $radius ** 3;

$PI = 3.0; # The 'Indiana maneuver' works!
PI = 3.0; # But this does not

In response to the last statement, Perl returns the error message, " Can't modify constant item in scalar assignment ."

constant.pm creates a subroutine of that name which returns the value you've assigned to it, so trying to overwrite it is like trying to assign a value to a subroutine call. Although the absurdity of that may sound like sufficient explanation for how use constant works, in fact, the latest version of perl allows you to assign a value to a subroutine call, provided the result of the subroutine is a place where you could store the value. For example, the subroutine could return a scalar variable. The term for this feature is lvaluable subroutine . But since the results of the subroutines created by use constant aren't lvalues, lvaluable subroutines won't cause problems for them.

[Dec 19, 2017] Cultured Perl: Debugging Perl with ease. Catch the bugs before they bite

Nov 01, 2000 | www.ibm.com

Bugs are as inevitable as death and taxes. Nevertheless, the following material should help you avoid the pitfalls of bugs.

... ... ...

First let's simply make sure the bug is repeatable. We'll set an action on line 8 to print $line where the error occurred, and run the program.

perl -d ./buggy.pl buggy.pl

use Data::Dumpe

a 8 print 'The line variable is now ', Dumper $line

The Data::Dumper module loads so that the autoaction can use a nice output format. The autoaction is set to do a print statement every time line 8 is reached. Now let's watch the show.

[Dec 08, 2017] Perl Debugger Tutorial 10 Easy Steps to Debug Perl Program

Dec 08, 2017 | www.thegeekstuff.com

Perl Debugger Tutorial: 10 Easy Steps to Debug Perl Program by Balakrishnan Mariyappan on May 19, 2010

https://apis.google.com/se/0/_/+1/fastbutton?usegapi=1&size=medium&origin=http%3A%2F%2Fwww.thegeekstuff.com&url=http%3A%2F%2Fwww.thegeekstuff.com%2F2010%2F05%2Fperl-debugger%2F&gsrc=3p&jsh=m%3B%2F_%2Fscs%2Fapps-static%2F_%2Fjs%2Fk%3Doz.gapi.en_US.7iE0RPXkeyg.O%2Fm%3D__features__%2Fam%3DAQ%2Frt%3Dj%2Fd%3D1%2Frs%3DAGLTcCPtrDcrcZ6TwfUke349lDWwAOzBUw#_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe%2C_renderstart%2Concircled%2Cdrefresh%2Cerefresh&id=I0_1512705132381&_gfid=I0_1512705132381&parent=http%3A%2F%2Fwww.thegeekstuff.com&pfname=&rpctoken=25025448

http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.thegeekstuff.com%2F2010%2F05%2Fperl-debugger%2F&send=false&layout=button_count&width=450&show_faces=false&action=like&colorscheme=light&font&height=21

http://platform.twitter.com/widgets/tweet_button.6b8337773e8a8ecc4f0b054fec8f1482.en.html#dnt=false&id=twitter-widget-0&lang=en&original_referer=http%3A%2F%2Fwww.thegeekstuff.com%2F2010%2F05%2Fperl-debugger%2F&size=m&text=Perl%20Debugger%20Tutorial%3A%2010%20Easy%20Steps%20to%20Debug%20Perl%20Program&time=1512705132548&type=share&url=http%3A%2F%2Fwww.thegeekstuff.com%2F2010%2F05%2Fperl-debugger%2F

Earlier we discussed the basics of how to write and execute a perl program using Perl Hello World Example .

In this article, Let us review how to debug a perl program / script using Perl debugger , which is similar to the gdb tool for debugging C code .

To debug a perl program, invoke the perl debugger using "perl -d" as shown below.

# perl -d  ./perl_debugger.pl

To understand the perl debugger commands in detail, let us create the following sample perl program (perl_debugger.pl).

$ cat perl_debugger.pl
#!/usr/bin/perl -w

# Script to list out the filenames (in the pwd) that contains specific pattern.

#Enabling slurp mode
$/=undef;

# Function : get_pattern
# Description : to get the pattern to be matched in files.
sub get_pattern
{
my $pattern;
print "Enter search string: ";
chomp ($pattern = <> );
return $pattern;
}

# Function : find_files
# Description : to get list of filenames that contains the input pattern.
sub find_files
{
my $pattern = shift;
my (@files,@list,$file);

# using glob, obtaining the filenames,
@files = <./*>;

# taking out the filenames that contains pattern.
@list = grep {
$file = $_;
open $FH,"$file";
@lines = <$FH>;
$count = grep { /$pattern/ } @lines;
$file if($count);
} @files;
return @list;
}
# to obtain the pattern from STDIN
$pattern = get_pattern();

# to find-out the list of filenames which has the input pattern.
@list = find_files($pattern);

print join "\n",@list;
1. Enter Perl Debugger

# perl -d ./perl_debugger.pl

it prompts,
DB<1>

2. View specific lines or subroutine statements using (l)

DB<1> l 10
10: my $pattern;

DB<2> l get_pattern
11 {
12: my $pattern;
13: print "Enter search string: ";
14: chomp ($pattern = );
15: return $pattern;
16 }

3. Set the breakpoint on get_pattern function using (b)

DB<3> b find_files

4. Set the breakpoint on specific line using (b)

DB<4> b 44

5. View the breakpoints using (L)

DB<5> L
./perl_debugger.pl:
22: my $pattern = shift;
break if (1)
44: print join "\n",@list;
break if (1)

6. step by step execution using (s and n)

DB<5> s
main::(./perl_debugger.pl:39): $pattern = get_pattern();

DB<5> s
main::get_pattern(./perl_debugger.pl:12):
12: my $pattern;

Option s and n does step by step execution of each statements. Option s steps into the subroutine. Option n executes the subroutine in a single step (stepping over it).

The s option does stepping into the subroutine but while n option which would execute the subroutine(stepping over it).

7. Continue till next breakpoint (or line number, or subroutine) using (c)

DB<5> c
Enter search string: perl
main::find_files(./perl_debugger.pl:22):
22: my $pattern = shift;

8. Continue down to the specific line number using (c)

DB<5> c 36
main::find_files(./perl_debugger.pl:36):
36: return @list;

9. Print the value in the specific variable using (p)

DB<6> p $pattern
perl

DB<7> c
main::(./perl_debugger.pl:44): print join "\n",@list;
DB<7> c
./perl_debugger.pl
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.

After the last continue operation, the output gets printed on the stdout as "./perl_debugger.pl" since it matches the pattern "perl".

10. Get debug commands from the file (source)

Perl debugger can get the debug command from the file and execute it. For example, create the file called "debug_cmds" with the perl debug commands as,

c
p $pattern
q

Note that R is used to restart the operation(no need quit and start debugger again).
DB<7> R
DB<7> source debug_cmds
>> c
Enter search string: perl
./perl_debugger.pl
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
>> p $pattern
perl
>> q

Note : If you are relatively new to perl, refer to our previous article: 20 perl programming tips for beginners .

Summary of perl debugger commands

Following options can be used once you enter the perl debugger.

[Dec 03, 2017] Debugging Regular Expressions

Dec 03, 2017 | my.safaribooksonline.com

Not for the fainthearted, if you want to see how a regular expression runs when used in a match or substitution, use the core re pragma with its debug option:

% perl -Mstrict -Mwarnings
use re qw(debug);
$_ = "cats=purr, dog=bark";
my %sound = /(\w+)=(\w+)/g;
^D
Compiling REx `(\w+)=(\w+)'
size 15 first at 4
1: OPEN1(3)
3: PLUS(5)
4: ALNUM(0)
5: CLOSE1(7)
7: EXACT <=>(9)
9: OPEN2(11)
11: PLUS(13)
12: ALNUM(0)
13: CLOSE2(15)
15: END(0)
floating `=' at 1..2147483647 (checking floating) stclass `ALNUM' plus
minlen 3
Guessing start of match, REx `(\w+)=(\w+)' against `cats=purr,
dog=bark'...
Found floating substr `=' at offset 4...
Does not contradict STCLASS...
Guessed: match at offset 0
Matching REx `(\w+)=(\w+)' against `cats=purr, dog=bark'
Setting an EVAL scope, savestack=3
0 <> <cats=purr, d> | 1: OPEN1
0 <> <cats=purr, d> | 3: PLUS
ALNUM can match 4 times out of 32767...
Setting an EVAL scope, savestack=3
4 <cats> <=purr, d> | 5: CLOSE1
4 <cats> <=purr, d> | 7: EXACT <=>
5 <cats=> <purr, d> | 9: OPEN2
5 <cats=> <purr, d> | 11: PLUS

Setting an EVAL scope, savestack=3
9 <=purr> <, dog=b> | 13: CLOSE2
9 <=purr> <, dog=b> | 15: END
Match successful!
Guessing start of match, REx `(\w+)=(\w+)' against `, dog=bark'...
Found floating substr `=' at offset 5...
By STCLASS: moving 0 --> 2
Guessed: match at offset 2
Matching REx `(\w+)=(\w+)' against `dog=bark'
Setting an EVAL scope, savestack=3
11 <urr, > <dog=bar> | 1: OPEN1
11 <urr, > <dog=bar> | 3: PLUS
ALNUM can match 3 times out of 32767...
Setting an EVAL scope, savestack=3
14 <rr, dog> <=bark> | 5: CLOSE1
14 <rr, dog> <=bark> | 7: EXACT <=>
15 <rr, dog=> <bark> | 9: OPEN2
15 <rr, dog=> <bark> | 11: PLUS
ALNUM can match 4 times out of 32767...
Setting an EVAL scope, savestack=3
19 <rr, dog=bark> <> | 13: CLOSE2
19 <rr, dog=bark> <> | 15: END
Match successful!
Freeing REx: `(\w+)=(\w+)'

debugcolor option instead of debug , you'll get some form of highlighting or coloring in the output that'll make it prettier, if not more understandable

[Dec 03, 2017] Just writing the tests is often a damn fine way of finding bugs

Nov 15, 2017 | perlmonks.com

GrandFather (Sage) on Jul 12, 2006 at 08:38 UTC

Re^2: Strategies for maintenance of horrible code?

Actually, just writing the tests is often a damn fine way of finding bugs. No exactly what OP is after at the moment, but something that is at the forefront of my mind because I'm in the middle of writing a set of tests (in Perl :) for some XML processing C++ code and turning up a pile of bugs as I go.

However it does suggest another test avenue: write test harnesses for modules so that you can exercise them in isolation and better understand how they work. If the test harness ends up part of a regression test system so much the better.


DWIM is Perl's answer to Gödel

[Dec 03, 2017] Strategies for maintenance of horrible code?

Notable quotes:
"... Debugging this code is a whole different game, and I'd really appreciate some input from other monks who've dealt with this type of problem. ..."
Jul 12, 2006 | perlmonks.com

converter has asked for the wisdom of the Perl Monks concerning the following question:

For the past several months I've been busy rewriting the horrible Perl code left behind by my predecessor. His approach to development was "Write some code. If the code runs without revealing any of the damage it's done, ship it. If not, write some more code."

This code is so bad that when co-workers ask me what I'm working on, I tell them "The Madman's Diary." Yes, it would have been cheaper and faster to throw this code away and start over, but I wasn't given that option.

My latest assignment is the repair of a tangled mess of a show-stopper that was discovered in a product that was supposed to ship today. After adding an open() override that logs the arguments to open() and some quality time with the watch(1) utility observing changes to the files containing the data that are causing the problem, I've narrowed the list of suspects down to a couple in-house scripts and a few (probably altered) webmin modules.

Now that I know where to look, I'd like to identify as quickly as possible which details can be safely ignored. I plan to use Devel::DProf to produce an execution graph for reference and Tie::Watch to watch variables, but I wonder if there are other tools that I should look at. A utility or module that would allow me to incrementally build a profile with persistent notes would be wonderful.

Debugging this code is a whole different game, and I'd really appreciate some input from other monks who've dealt with this type of problem.

eyepopslikeamosquito (Chancellor) on Jul 12, 2006 at 08:30 UTC

Re: Strategies for maintenance of horrible code?
Yes, it would have been cheaper and faster to throw this code away and start over
Maybe. For another point of view, see Joel Spolsky on not rewriting from scratch .

I agree with adrianh . If a component is not broken, don't rewrite it. Rewrite a component when you find a number of bugs in it. But first write a regression test suite for the component. I've seen many folks over the years throw out old code, rewrite it ... and introduce a heap of new bugs in the process. If you come into a new company and introduce a swag of new bugs in previously working code, you will start to smell very badly.

See also:

GrandFather (Sage) on Jul 12, 2006 at 08:38 UTC

Re^2: Strategies for maintenance of horrible code?

Actually, just writing the tests is often a damn fine way of finding bugs. No exactly what OP is after at the moment, but something that is at the forefront of my mind because I'm in the middle of writing a set of tests (in Perl :) for some XML processing C++ code and turning up a pile of bugs as I go.

However it does suggest another test avenue: write test harnesses for modules so that you can exercise them in isolation and better understand how they work. If the test harness ends up part of a regression test system so much the better.


DWIM is Perl's answer to Gödel

tinita (Parson) on Jul 12, 2006 at 12:28 UTC

Maybe. For another point of view, see Joel Spolsky on not rewriting from scratch.
uh oh. why does this remind me of perl 6? =)

adrianh (Chancellor) on Jul 12, 2006 at 07:49 UTC

Debugging this code is a whole different game, and I'd really appreciate some input from other monks who've dealt with this type of problem.

I'd recommend reading Perl Medic and Working Effectively with Legacy Code (the latter isn't Perl specific - but is chock full of useful advice).

I would not spend any time fixing the code if it's not breaking (assuming you're not being paid to review/fix the code). However evil it may be - if it's doing it's job leave it alone.

Instead - every time you need to fix a bug or add some new functionality just test/refactor the bits of the evil code that are touched by the changes. I've found incrementally adding tests and refactoring to be much more effective than any sort of "big bang" fixing things for the sake of them approach :-)

If you are being paid to do a review/fix then Perl::Critic might give you some useful places to look.

webfiend (Vicar) on Jul 14, 2006 at 21:24 UTC

Definitely agree about the approach of sorting things out with gradual refactoring and tests as the need arises. The problem with the "Big Bang" approach is that you have the potential for a very long stretch of time where there are two forks of the code: ugly shipping code that will need to be fixed and refactored as bugs are reported, and pretty nonfunctioning code that will need to incorporate those fixes as they are uncovered, resulting in a perpetual loop of "it's not quite ready yet."

Ovid (Cardinal) on Jul 12, 2006 at 10:37 UTC

Check out Suggestions for working with poor code and some of the replies.

Cheers,
Ovid

New address of my CGI Course .

GrandFather (Sage) on Jul 12, 2006 at 07:39 UTC

Re: Strategies for maintenance of horrible code?

What tools are you using already and on what platform? For a large range of "detail" debugging there is nothing like as good as an IDE with a good integrated debugger. For a higher level view of where things are going Devel::TraceCalls may be handy, although it's output can be rather voluminous.


DWIM is Perl's answer to Gödel

Moron (Curate) on Jul 12, 2006 at 12:13 UTC

Some basic CYA I can see:

1) Ensure there is sufficient functional and technical design documentation against which the routines can be tested.

2) (updated) Make sure there is a sufficiently detailed project plan to include tasks for: systems analysis, functional and technical design, test planning, test script writing (e.g. using Expect ), developing, unit-, integrated and functional testing, rework and implementation, to include a GANTT chart of the work done so far and by who to what % of completion, to avoid getting the blame for not meeting poorly conceived targets over which you had no control.

In response to formal testing against the plan, I find it a useful aid to bug-fixing to monitor execution with perl -d, setting breakpoints and examining variables to hunt down which line of code causes each failure.

-M

Free your mind

aufflick (Deacon) on Jul 13, 2006 at 00:17 UTC

You might find the comments to my recent question Generating documentation from Perl code (not just POD) useful.

The Doxygen perl extension creates docs that are great for seeing what classes re-implement what methods etc. Also the UML::Sequence sounds intriguing - it pupports to generate a sequence diagram by monitoring code execution.

[Dec 03, 2017] Core module Tie::File - Access the lines of a disk file via a Perl array

Dec 03, 2017 | perldoc.perl.org

Tie::File

NAME

Tie::File - Access the lines of a disk file via a Perl array

SYNOPSIS
  1. # This file documents Tie::File version 0.98
  2. use Tie::File
  3. tie @array 'Tie::File' filename or die ...
  4. $array 13 ] = 'blah' # line 13 of the file is now 'blah'
  5. print $array 42 # display line 42 of the file
  6. $n_recs = @array # how many records are in the file?
  7. $#array -= # chop two records off the end
  8. for @array
  9. s/PERL/Perl/g # Replace PERL with Perl everywhere in the file
  10. # These are just like regular push, pop, unshift, shift, and splice
  11. # Except that they modify the file in the way you would expect
  12. push @array new recs ...
  13. my $r1 = pop @array
  14. unshift @array new recs ...
  15. my $r2 = shift @array
  16. @old_recs = splice @array new recs ...
  17. untie @array # all finished
DESCRIPTION

Tie::File represents a regular text file as a Perl array. Each element in the array corresponds to a record in the file. The first line of the file is element 0 of the array; the second line is element 1, and so on.

The file is not loaded into memory, so this will work even for gigantic files.

Changes to the array are reflected in the file immediately.

Lazy people and beginners may now stop reading the manual.

recsep

What is a 'record'? By default, the meaning is the same as for the <...> operator: It's a string terminated by $/ , which is probably "\n" . (Minor exception: on DOS and Win32 systems, a 'record' is a string terminated by "\r\n" .) You may change the definition of "record" by supplying the recsep option in the tie call:

  1. tie @array 'Tie::File' $file recsep => 'es'

This says that records are delimited by the string es . If the file contained the following data:

  1. Curse these pesky flies !\

then the @array would appear to have four elements:

  1. "Curse th"
  2. "e p"
  3. "ky fli"
  4. "!\n"

An undefined value is not permitted as a record separator. Perl's special "paragraph mode" semantics (à la $/ = "" ) are not emulated.

Records read from the tied array do not have the record separator string on the end; this is to allow

  1. $array 17 ] .= "extra"

to work as expected.

(See autochomp , below.) Records stored into the array will have the record separator string appended before they are written to the file, if they don't have one already. For example, if the record separator string is "\n" , then the following two lines do exactly the same thing:

  1. $array 17 ] = "Cherry pie"
  2. $array 17 ] = "Cherry pie\n"

The result is that the contents of line 17 of the file will be replaced with "Cherry pie"; a newline character will separate line 17 from line 18. This means that this code will do nothing:

  1. chomp $array 17

Because the chomp ed value will have the separator reattached when it is written back to the file. There is no way to create a file whose trailing record separator string is missing.

Inserting records that contain the record separator string is not supported by this module. It will probably produce a reasonable result, but what this result will be may change in a future version. Use 'splice' to insert records or to replace one record with several.

autochomp

Normally, array elements have the record separator removed, so that if the file contains the text

  1. Gold
  2. Frankincense
  3. Myrrh

the tied array will appear to contain "Gold" "Frankincense" "Myrrh" . If you set autochomp to a false value, the record separator will not be removed. If the file above was tied with

  1. tie @gifts "Tie::File" $gifts autochomp =>

then the array @gifts would appear to contain "Gold\n" "Frankincense\n" "Myrrh\n" , or (on Win32 systems) "Gold\r\n" "Frankincense\r\n" "Myrrh\r\n" .

mode

Normally, the specified file will be opened for read and write access, and will be created if it does not exist. (That is, the flags O_RDWR | O_CREAT are supplied in the open call.) If you want to change this, you may supply alternative flags in the mode option. See Fcntl for a listing of available flags. For example:

  1. # open the file if it exists, but fail if it does not exist
  2. use Fcntl 'O_RDWR'
  3. tie @array 'Tie::File' $file mode => O_RDWR
  4. # create the file if it does not exist
  5. use Fcntl 'O_RDWR' 'O_CREAT'
  6. tie @array 'Tie::File' $file mode => O_RDWR | O_CREAT
  7. # open an existing file in read-only mode
  8. use Fcntl 'O_RDONLY'
  9. tie @array 'Tie::File' $file mode => O_RDONLY

Opening the data file in write-only or append mode is not supported.

memory

This is an upper limit on the amount of memory that Tie::File will consume at any time while managing the file. This is used for two things: managing the read cache and managing the deferred write buffer .

Records read in from the file are cached, to avoid having to re-read them repeatedly. If you read the same record twice, the first time it will be stored in memory, and the second time it will be fetched from the read cache . The amount of data in the read cache will not exceed the value you specified for memory . If Tie::File wants to cache a new record, but the read cache is full, it will make room by expiring the least-recently visited records from the read cache.

The default memory limit is 2Mib. You can adjust the maximum read cache size by supplying the memory option. The argument is the desired cache size, in bytes.

  1. # I have a lot of memory, so use a large cache to speed up access
  2. tie @array 'Tie::File' $file memory => 20_000_000

Setting the memory limit to 0 will inhibit caching; records will be fetched from disk every time you examine them.

The memory value is not an absolute or exact limit on the memory used. Tie::File objects contains some structures besides the read cache and the deferred write buffer, whose sizes are not charged against memory .

The cache itself consumes about 310 bytes per cached record, so if your file has many short records, you may want to decrease the cache memory limit, or else the cache overhead may exceed the size of the cached data.

dw_size

(This is an advanced feature. Skip this section on first reading.)

If you use deferred writing (See Deferred Writing , below) then data you write into the array will not be written directly to the file; instead, it will be saved in the deferred write buffer to be written out later. Data in the deferred write buffer is also charged against the memory limit you set with the memory option.

You may set the dw_size option to limit the amount of data that can be saved in the deferred write buffer. This limit may not exceed the total memory limit. For example, if you set dw_size to 1000 and memory to 2500, that means that no more than 1000 bytes of deferred writes will be saved up. The space available for the read cache will vary, but it will always be at least 1500 bytes (if the deferred write buffer is full) and it could grow as large as 2500 bytes (if the deferred write buffer is empty.)

If you don't specify a dw_size , it defaults to the entire memory limit.

Option Format

- mode is a synonym for mode . - recsep is a synonym for recsep . - memory is a synonym for memory . You get the idea.

Public Methods

The tie call returns an object, say $o . You may call

  1. $rec = $o->FETCH $n
  2. $o->STORE $n $rec

to fetch or store the record at line $n , respectively; similarly the other tied array methods. (See perltie for details.) You may also call the following methods on this object:

flock
  1. $o->flock MODE

will lock the tied file. MODE has the same meaning as the second argument to the Perl built-in flock function; for example LOCK_SH or LOCK_EX | LOCK_NB . (These constants are provided by the use Fcntl ':flock' declaration.)

MODE is optional; the default is LOCK_EX .

Tie::File maintains an internal table of the byte offset of each record it has seen in the file.

When you use flock to lock the file, Tie::File assumes that the read cache is no longer trustworthy, because another process might have modified the file since the last time it was read. Therefore, a successful call to flock discards the contents of the read cache and the internal record offset table.

Tie::File promises that the following sequence of operations will be safe:

  1. my $o = tie @array "Tie::File" $filename
  2. $o->flock

In particular, Tie::File will not read or write the file during the tie call. (Exception: Using mode => O_TRUNC will, of course, erase the file during the tie call. If you want to do this safely, then open the file without O_TRUNC , lock the file, and use @array = () .)

The best way to unlock a file is to discard the object and untie the array. It is probably unsafe to unlock the file without also untying it, because if you do, changes may remain unwritten inside the object. That is why there is no shortcut for unlocking. If you really want to unlock the file prematurely, you know what to do; if you don't know what to do, then don't do it.

All the usual warnings about file locking apply here. In particular, note that file locking in Perl is advisory , which means that holding a lock will not prevent anyone else from reading, writing, or erasing the file; it only prevents them from getting another lock at the same time. Locks are analogous to green traffic lights: If you have a green light, that does not prevent the idiot coming the other way from plowing into you sideways; it merely guarantees to you that the idiot does not also have a green light at the same time.

autochomp
  1. my $old_value = $o->autochomp # disable autochomp option
  2. my $old_value = $o->autochomp # enable autochomp option
  3. my $ac = $o->autochomp () # recover current value

See autochomp , above.

defer , flush , discard , and autodefer

See Deferred Writing , below.

offset
  1. $off = $o->offset $n

This method returns the byte offset of the start of the $n th record in the file. If there is no such record, it returns an undefined value.

Tying to an already-opened filehandle

If $fh is a filehandle, such as is returned by IO::File or one of the other IO modules, you may use:

  1. tie @array 'Tie::File' $fh ...

Similarly if you opened that handle FH with regular open or sysopen , you may use:

  1. tie @array 'Tie::File' \ *FH ...

Handles that were opened write-only won't work. Handles that were opened read-only will work as long as you don't try to modify the array. Handles must be attached to seekable sources of data---that means no pipes or sockets. If Tie::File can detect that you supplied a non-seekable handle, the tie call will throw an exception. (On Unix systems, it can detect this.)

Note that Tie::File will only close any filehandles that it opened internally. If you passed it a filehandle as above, you "own" the filehandle, and are responsible for closing it after you have untied the @array.

Deferred Writing

(This is an advanced feature. Skip this section on first reading.)

Normally, modifying a Tie::File array writes to the underlying file immediately. Every assignment like $a ] = ... rewrites as much of the file as is necessary; typically, everything from line 3 through the end will need to be rewritten. This is the simplest and most transparent behavior. Performance even for large files is reasonably good.

However, under some circumstances, this behavior may be excessively slow. For example, suppose you have a million-record file, and you want to do:

  1. for @FILE
  2. $_ = "> $_"

The first time through the loop, you will rewrite the entire file, from line 0 through the end. The second time through the loop, you will rewrite the entire file from line 1 through the end. The third time through the loop, you will rewrite the entire file from line 2 to the end. And so on.

If the performance in such cases is unacceptable, you may defer the actual writing, and then have it done all at once. The following loop will perform much better for large files:

  1. tied @a ->defer
  2. for @a
  3. $_ = "> $_"
  4. tied @a ->flush

If Tie::File 's memory limit is large enough, all the writing will done in memory. Then, when you call ->flush , the entire file will be rewritten in a single pass.

(Actually, the preceding discussion is something of a fib. You don't need to enable deferred writing to get good performance for this common case, because Tie::File will do it for you automatically unless you specifically tell it not to. See autodeferring , below.)

Calling ->flush returns the array to immediate-write mode. If you wish to discard the deferred writes, you may call ->discard instead of ->flush . Note that in some cases, some of the data will have been written already, and it will be too late for ->discard to discard all the changes. Support for ->discard may be withdrawn in a future version of Tie::File .

Deferred writes are cached in memory up to the limit specified by the dw_size option (see above). If the deferred-write buffer is full and you try to write still more deferred data, the buffer will be flushed. All buffered data will be written immediately, the buffer will be emptied, and the now-empty space will be used for future deferred writes.

If the deferred-write buffer isn't yet full, but the total size of the buffer and the read cache would exceed the memory limit, the oldest records will be expired from the read cache until the total size is under the limit.

push , pop , shift , unshift , and splice cannot be deferred. When you perform one of these operations, any deferred data is written to the file and the operation is performed immediately. This may change in a future version.

If you resize the array with deferred writing enabled, the file will be resized immediately, but deferred records will not be written. This has a surprising consequence: @a = ... erases the file immediately, but the writing of the actual data is deferred. This might be a bug. If it is a bug, it will be fixed in a future version.

Autodeferring

Tie::File tries to guess when deferred writing might be helpful, and to turn it on and off automatically.

  1. for @a
  2. $_ = "> $_"

In this example, only the first two assignments will be done immediately; after this, all the changes to the file will be deferred up to the user-specified memory limit.

You should usually be able to ignore this and just use the module without thinking about deferring. However, special applications may require fine control over which writes are deferred, or may require that all writes be immediate. To disable the autodeferment feature, use

  1. tied @o ->autodefer

or

  1. tie @array 'Tie::File' $file autodefer =>

Similarly, ->autodefer re-enables autodeferment, and ->autodefer () recovers the current value of the autodefer setting.

CONCURRENT ACCESS TO FILES

Caching and deferred writing are inappropriate if you want the same file to be accessed simultaneously from more than one process. Other optimizations performed internally by this module are also incompatible with concurrent access. A future version of this module will support a concurrent => option that enables safe concurrent access.

Previous versions of this documentation suggested using memory => for safe concurrent access. This was mistaken. Tie::File will not support safe concurrent access before version 0.96.

CAVEATS

(That's Latin for 'warnings'.)

SUBCLASSING

This version promises absolutely nothing about the internals, which may change without notice. A future version of the module will have a well-defined and stable subclassing API.

WHAT ABOUT DB_File ?

People sometimes point out that DB_File will do something similar, and ask why Tie::File module is necessary.

There are a number of reasons that you might prefer Tie::File . A list is available at http://perl.plover.com/TieFile/why-not-DB_File .

AUTHOR

Mark Jason Dominus

To contact the author, send email to: mjd perl tiefile @plover com

To receive an announcement whenever a new version of this module is released, send a blank email message to mjd perl tiefile subscribe @plover com .

The most recent version of this module, including documentation and any news of importance, will be available at

  1. http://perl.plover.com/TieFile/
LICENSE

Tie::File version 0.96 is copyright (C) 2003 Mark Jason Dominus.

This library is free software; you may redistribute it and/or modify it under the same terms as Perl itself.

These terms are your choice of any of (1) the Perl Artistic Licence, or (2) version 2 of the GNU General Public License as published by the Free Software Foundation, or (3) any later version of the GNU General Public License.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this library program; it should be in the file COPYING . If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA

For licensing inquiries, contact the author at:

  1. Mark Jason Dominus
  2. 255 S. Warnock St.
  3. Philadelphia, PA 19107
WARRANTY

Tie::File version 0.98 comes with ABSOLUTELY NO WARRANTY. For details, see the license.

THANKS

[Dec 01, 2017] regex - Debugging Perl Regular expression

Dec 01, 2017 | stackoverflow.com

down vote favorite 1

AnonGeek ,Jun 20, 2012 at 20:37

I am trying to debug few regular expressions using:
perl -Mre=debug file.pl

The file.pl script has many regular expression. Some of them are repeated. Using above syntax, all the regex in file.pl are being debugged.

Is there a way to tell Perl to debug only a particular regex in a script?

I am familiar with YAPE::Regex module, but that is not what I require. So please don't suggest to use that.

Ehtesh Choudhury ,Jun 20, 2012 at 20:45

Why not just comment out the other regexes, or run just the particular regex on the command line, via perl -e ? – Ehtesh Choudhury Jun 20 '12 at 20:45

AnonGeek ,Jun 20, 2012 at 20:55

the script is very compilcated(12000 LOC). If I will comment out any of regex then the execution will fail..Also if I provide dummy values, then it will give unexpected results :( – AnonGeek Jun 20 '12 at 20:55

Oleg V. Volkov ,Jun 20, 2012 at 20:41

As with many other pragmas, you can use no to cancel previous use .
use re 'debug';

$str=~/\d{3}/;

no re 'debug';

$str=~/\d{3}/;

Denis Ibaev ,Jun 20, 2012 at 20:48

As of 5.9.5 the directive use re 'debug' and its equivalents are lexically scoped, as the other directives are.

Use:

{
    use re 'debug';
    # Debugged regexp here.
}

AnonGeek ,Jun 20, 2012 at 21:10

Is this also supported in 5.8.8? I am putting it under a condition but it is enabling it globally for all regex. – AnonGeek Jun 20 '12 at 21:10

Denis Ibaev ,Jun 21, 2012 at 5:24

No, since version 5.9.5. In 5.8.8 you need use no statement. – Denis Ibaev Jun 21 '12 at 5:24

[Nov 30, 2017] debugging - Perl Debugger Filehandle as Input

Highly recommended!
Nov 30, 2017 | stackoverflow.com
I have this problem: I need to control the perl-debugger from an external script. By research I found out about various solutions, but I don't understand them. I failed to properly set up the RemotePort option (editing ".perldb"), which was the first I tried, and found no useful information on providing a filehandle from which the debugger would get its input (by somehow setting @cmdfhs) I found both options over here: http://search.cpan.org/~nwclark/perl-5.8.6/lib/perl5db.pl

It would be nice if you could tell me how to provide the filehandle from which the debugger gets its input, or if you know a link where this is explained?

Casper ,Jun 28, 2015 at 21:53

Here's a simple example setting it up using RemotePort , which seemed easier to me:

The trick to using RemotePort is that you have to have someone listening on the remote end BEFORE you launch the script to be debugged.

As soon as you launch your script with -d Perl will attempt to connect to RemotePort . So you have to make sure the initial connection succeeds by having someone listening there beforehand.

Here I assume some Linux/Unix variant, which has the netcat utility installed. We use netcat to wait for incoming connections in this example, but you can use anything else you wish too which is able to create a service port and shuffle data between that and the current TTY:

In terminal 1

 # Use netcat to listen for incoming connections on port 9999
 > nc -l -p 9999

In terminal 2

 # Start perl with -d and request a RemotePort connection 
 > PERLDB_OPTS=RemotePort=127.0.0.1:9999 perl -d my_script.pl

As soon as you do that in terminal 1 you will see something like this:

Loading DB routines from perl5db.pl version 1.39_10
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(my_script.pl:4):
  DB<1>

There you go..debug away.

Devel::Trepan is a gdb-like debugger. Although it has remote control, you can also run it at the outset with the option --command which will "source" (in the gdb-sense) or run a series of debugger commands.

To go into remote control, either start the debugger using the --server option or inside the debugger use the " server " command once inside the debugger.

See Options for a list of options you can give at the outset.

[Nov 30, 2017] Working with character arrays in perl

Nov 30, 2017 | stackoverflow.com

up vote down vote

cbg ,Jul 7, 2014 at 11:36

my @char_array = split "", $s1;

@char_array now contains all the characters of the $s1 string and it's possible to manipulate it, iterate over it or do whatever to it just like with any other array.

You can you splice to insert elements at a given position of the array:
echo -e 'hello\ndisk\ncaller' | perl -F'' -ane ' splice (@F,2,0," "); splice(@F,4,0," "); foreach(@F){print}'
he l lo
di s k
ca l ler

You can use Data::Dumper for better visualization when working with arrays:

echo -n 'hello' | perl -MData::Dumper -F'' -ane ' splice (@F,2,0," "); splice(@F,4,0," ");print Dumper(\@F)'
$VAR1 = [
          'h',
          'e',
          ' ',
          'l',
          ' ',
          'l',
          'o'
        ];

[Nov 30, 2017] Working with character arrays in perl

Nov 30, 2017 | stackoverflow.com

up vote down vote

cbg ,Jul 7, 2014 at 11:36

my @char_array = split "", $s1;

@char_array now contains all the characters of the $s1 string and it's possible to manipulate it, iterate over it or do whatever to it just like with any other array.

You can you splice to insert elements at a given position of the array:
echo -e 'hello\ndisk\ncaller' | perl -F'' -ane ' splice (@F,2,0," "); splice(@F,4,0," "); foreach(@F){print}'
he l lo
di s k
ca l ler

You can use Data::Dumper for better visualization when working with arrays:

echo -n 'hello' | perl -MData::Dumper -F'' -ane ' splice (@F,2,0," "); splice(@F,4,0," ");print Dumper(\@F)'
$VAR1 = [
          'h',
          'e',
          ' ',
          'l',
          ' ',
          'l',
          'o'
        ];

[Nov 29, 2017] How can I have variable assertions in Perl

Notable quotes:
"... Smart::Comments++ When used with the -ENV switch, it's a fantastic tool for this sort of thing. Much better than having to strip all the tests out before going to production, as someone else suggested. ..."
Nov 29, 2017 | stackoverflow.com

Alex ,Jun 21, 2009 at 12:45

How can I check that a variable has a specific value in Perl? Is there a command to stop a script's execution to look up some of it's variables?

I wonder if I can use the Pythonic practice of inserting:

    assert 0, (foo, bar)

to debug scripts in a debuger-less way?

Telemachus ,Jun 21, 2009 at 12:58

A quick CPAN search suggests Carp::Assert .

Sinan Ünür ,Jun 21, 2009 at 13:30

+1 for typing in more characters faster than I did. I am going to edit the URL to be version agnostic though. – Sinan Ünür Jun 21 '09 at 13:30

Telemachus ,Jun 21, 2009 at 13:50

I was going to comment on your answer about the photo finish. As for the URL, I constantly forget that, so thanks. – Telemachus Jun 21 '09 at 13:50

Sinan Ünür ,Jun 21, 2009 at 12:58

See Carp::Assert .

zoul ,Jun 21, 2009 at 13:44

Smart::Comments are nice.

RET ,Jun 22, 2009 at 3:28

Smart::Comments++ When used with the -ENV switch, it's a fantastic tool for this sort of thing. Much better than having to strip all the tests out before going to production, as someone else suggested.

RET Jun 22 '09 at 3:28

nik ,Jun 21, 2009 at 12:54

There is a script at PerlMonks that introduces a fast assert method.

Speed is important since Perl is interpreted and any inline checks will impact performance (unlike simple C macros for example)


I am not sure if these things are going to be directly usable.


Ok! This is what i was looking for -- PDF Warning: Test-Tutorial.pdf . The Test::Harness is used for writing Perl module tests.

Ape-inago ,Jun 21, 2009 at 13:51

$var_to_check =~ /sometest/ or die "bad variable!";

I tend to throw things like this in my code, and later use a find and replace to get rid of them (in production code).

Also, ' eval ' can be used to run a section of code and capture errors and can be used to create exception handling functionality. If you are asserting that a value is not 0, perhaps you want to throw an exception and handle that case in a special way?

> ,

if ( $next_sunrise_time > 24*60*60 ) { warn( "assertion failed" ); } # Assert that the sun must rise in the next 24 hours.

You can do this if you do not have access to Perl 5.9 which is required for Carp::Assert .

[Nov 29, 2017] How can I have variable assertions in Perl

Nov 29, 2017 | stackoverflow.com

Alex ,Jun 21, 2009 at 12:45

How can I check that a variable has a specific value in Perl? Is there a command to stop a script's execution to look up some of it's variables?

I wonder if I can use the Pythonic practice of inserting:

    assert 0, (foo, bar)

to debug scripts in a debuger-less way?

Telemachus ,Jun 21, 2009 at 12:58

A quick CPAN search suggests Carp::Assert .

Sinan Ünür ,Jun 21, 2009 at 13:30

+1 for typing in more characters faster than I did. I am going to edit the URL to be version agnostic though. – Sinan Ünür Jun 21 '09 at 13:30

Telemachus ,Jun 21, 2009 at 13:50

I was going to comment on your answer about the photo finish. As for the URL, I constantly forget that, so thanks. – Telemachus Jun 21 '09 at 13:50

Sinan Ünür ,Jun 21, 2009 at 12:58

See Carp::Assert .

zoul ,Jun 21, 2009 at 13:44

Smart::Comments are nice.

RET ,Jun 22, 2009 at 3:28

Smart::Comments++ When used with the -ENV switch, it's a fantastic tool for this sort of thing. Much better than having to strip all the tests out before going to production, as someone else suggested.

RET Jun 22 '09 at 3:28

nik ,Jun 21, 2009 at 12:54

There is a script at PerlMonks that introduces a fast assert method.

Speed is important since Perl is interpreted and any inline checks will impact performance (unlike simple C macros for example)


I am not sure if these things are going to be directly usable.


Ok! This is what i was looking for -- PDF Warning: Test-Tutorial.pdf . The Test::Harness is used for writing Perl module tests.

Ape-inago ,Jun 21, 2009 at 13:51

$var_to_check =~ /sometest/ or die "bad variable!";

I tend to throw things like this in my code, and later use a find and replace to get rid of them (in production code).

Also, ' eval ' can be used to run a section of code and capture errors and can be used to create exception handling functionality. If you are asserting that a value is not 0, perhaps you want to throw an exception and handle that case in a special way?

> ,

if ( $next_sunrise_time > 24*60*60 ) { warn( "assertion failed" ); } # Assert that the sun must rise in the next 24 hours.

You can do this if you do not have access to Perl 5.9 which is required for Carp::Assert .

[Nov 23, 2017] A Perl array 'contains' example by Alvin Alexander

Jun 03, 2016 | alvinalexander.com

Perl array FAQ: How can I test to see if a Perl array already contains a given value? (Also written as, How do I search an array with the Perl grep function?)

I use the Perl grep function to see if a Perl array contains a given entry. For instance, in this Perl code:

if ( grep { $_ eq $clientAddress} @ip_addresses ) {
  # the array already contains this ip address; skip it this time
  next;
} else {
  # the array does not yet contain this ip address; add it
  push @ip_addresses, $clientAddress;
}

I'm testing to see if the Perl array "@ip_addresses" contains an entry given by the variable "$clientAddress".

Just use this Perl array search technique in an "if" clause, as shown, and then add whatever logic you want within your if and else statements. In this case, if the current IP address is not already in the array, I add it to the array in the "else" clause, but of course your logic will be unique.

An easier "Perl array contains" example

If it's easier to read without a variable in there, here's another example of this "Perl array contains" code:

if ( grep { $_ eq '192.168.1.100'} @ip_addresses )

if you'd like more details, I didn't realize it, but I have another good example out here in my " Perl grep array tutorial ." (It's pretty bad when you can't find things on your own website.)

[Nov 22, 2017] edited yesterday

Notable quotes:
"... Comment on possible multiple conflicting options ..."
"... Higher-Order Perl ..."
Nov 22, 2017 | stackoverflow.com

down vote favorite

Speeddymon ,2 days ago

I've been reading up on dispatch tables and I get the general idea of how they work, but I'm having some trouble taking what I see online and applying the concept to some code I originally wrote as an ugly mess of if-elsif-else statements.

I have options parsing configured by using GetOpt::Long , and in turn, those options set a value in the %OPTIONS hash, depending on the option used.

Taking the below code as an example... ( UPDATED WITH MORE DETAIL

use     5.008008;
use     strict;
use     warnings;
use     File::Basename qw(basename);
use     Getopt::Long qw(HelpMessage VersionMessage :config posix_default require_order no_ignore_case auto_version auto_help);

my $EMPTY      => q{};

sub usage
{
    my $PROG = basename($0);
    print {*STDERR} $_ for @_;
    print {*STDERR} "Try $PROG --help for more information.\n";
    exit(1);
}

sub process_args
{
    my %OPTIONS;

    $OPTIONS{host}              = $EMPTY;
    $OPTIONS{bash}              = 0;
    $OPTIONS{nic}               = 0;
    $OPTIONS{nicName}           = $EMPTY;
    $OPTIONS{console}           = 0;
    $OPTIONS{virtual}           = 0;
    $OPTIONS{cmdb}              = 0;
    $OPTIONS{policyid}          = 0;
    $OPTIONS{showcompliant}     = 0;
    $OPTIONS{backup}            = 0;
    $OPTIONS{backuphistory}     = 0;
    $OPTIONS{page}              = $EMPTY;

    GetOptions
      (
        'host|h=s'              => \$OPTIONS{host}               ,
        'use-bash-script'       => \$OPTIONS{bash}               ,
        'remote-console|r!'     => \$OPTIONS{console}            ,
        'virtual-console|v!'    => \$OPTIONS{virtual}            ,
        'nic|n!'                => \$OPTIONS{nic}                ,
        'nic-name|m=s'          => \$OPTIONS{nicName}            ,
        'cmdb|d!'               => \$OPTIONS{cmdb}               ,
        'policy|p=i'            => \$OPTIONS{policyid}           ,
        'show-compliant|c!'     => \$OPTIONS{showcompliant}      ,
        'backup|b!'             => \$OPTIONS{backup}             ,
        'backup-history|s!'     => \$OPTIONS{backuphistory}      ,
        'page|g=s'              => \$OPTIONS{page}               ,
        'help'                  => sub      { HelpMessage(-exitval => 0, -verbose ->1)     },
        'version'               => sub      { VersionMessage()  },
      ) or usage;

    if ($OPTIONS{host} eq $EMPTY)
    {
        print {*STDERR} "ERROR: Must specify a host with -h flag\n";
        HelpMessage;
    }

    sanity_check_options(\%OPTIONS);

    # Parse anything else on the command line and throw usage
    for (@ARGV)
    {
        warn "Unknown argument: $_\n";
        HelpMessage;
    }

    return {%OPTIONS};
}

sub sanity_check_options
{
    my $OPTIONS     = shift;

    if (($OPTIONS->{console}) and ($OPTIONS->{virtual}))
    {
        print "ERROR: Cannot use flags -r and -v together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{console}) and ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flags -r and -d together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{console}) and ($OPTIONS->{backup}))
    {
        print "ERROR: Cannot use flags -r and -b together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{console}) and ($OPTIONS->{nic}))
    {
        print "ERROR: Cannot use flags -r and -n together\n";
        HelpMessage;
    }

    if (($OPTIONS->{virtual}) and ($OPTIONS->{backup}))
    {
        print "ERROR: Cannot use flags -v and -b together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{virtual}) and ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flags -v and -d together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{virtual}) and ($OPTIONS->{nic}))
    {
        print "ERROR: Cannot use flags -v and -n together\n";
        HelpMessage;
    }

    if (($OPTIONS->{backup}) and ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flags -b and -d together\n";
        HelpMessage;
    }
    elsif (($OPTIONS->{backup}) and ($OPTIONS->{nic}))
    {
        print "ERROR: Cannot use flags -b and -n together\n";
        HelpMessage;
    }

    if (($OPTIONS->{nic}) and ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flags -n and -d together\n";
        HelpMessage;
    }

    if (($OPTIONS->{policyid} != 0) and not ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flag -p without also specifying -d\n";
        HelpMessage;
    }

    if (($OPTIONS->{showcompliant}) and not ($OPTIONS->{cmdb}))
    {
        print "ERROR: Cannot use flag -c without also specifying -d\n";
        HelpMessage;
    }

    if (($OPTIONS->{backuphistory}) and not ($OPTIONS->{backup}))
    {
        print "ERROR: Cannot use flag -s without also specifying -b\n";
        HelpMessage;
    }

    if (($OPTIONS->{nicName}) and not ($OPTIONS->{nic}))
    {
        print "ERROR: Cannot use flag -m without also specifying -n\n";
        HelpMessage;
    }

    return %{$OPTIONS};
}

I'd like to turn the above code into a dispatch table, but can't figure out how to do it.

Any help is appreciated.

Jim Garrison ,2 days ago

Are the sets of conflicting options always pairs? Can you have situations where options a , b , and c cannot occur together but any two are OK? Before you can pick a representation you need to be sure your model can handle the logic you need in a general way. This is not an easy problem. – Jim Garrison 2 days ago

simbabque ,yesterday

Don't use English, it's horribly slow and makes your code harder to read. – simbabque yesterday

Speeddymon ,yesterday

Removed English module and changed $ARG / @ARG to $_ / @_ Added $EMPTY as I forgot I had it defined globally. – Speeddymon yesterday

Speeddymon ,yesterday

@JimGarrison -- you are correct. The if-elsif-else does not explicitly account for 3 options that conflict (though it does account for that implicitly) As an example, using -h is required with all of the other options. But, using -h , -r , v , all together is not allowed, while -h , -r , and -d is allowed. – Speeddymon yesterday

ikegami ,yesterday

Since the host must be provided, it should be an argument, not an option. – ikegami yesterday

zdim ,2 days ago

I am not sure how a dispatch table would help since you need to go through pair-wise combinations of specific possibilities, and thus cannot trigger a suitable action by one lookup.

Here is another way to organize it

use List::MoreUtils 'firstval';

sub sanity_check_options
{
    my ($OPTIONS, $opt_excl) = @_;

    # Check each of 'opt_excl' against all other for ConFLict
    my @excl = sort keys %$opt_excl;
    while (my $eo = shift @excl) 
    {
        if (my $cfl = firstval { $OPTIONS->{$eo} and $OPTIONS->{$_} } @excl) 
        {
            say "Can't use -$opt_excl->{$eo} and -$opt_excl->{$cfl} together";
            HelpMessage();
            last;
        }
    }

    # Go through specific checks on
    # policyid, showcompliant, backuphistory, and nicName
    ...
    return 1;  # or some measure of whether there were errors
}

# Mutually exclusive options
my %opt_excl = (
    console => 'r', virtual => 'v', cmdb => 'c', backup => 'b', nic => 'n'
); 

sanity_check_options(\%OPTIONS, \%opt_excl);

This checks all options listed in %opt_excl against each other for conflict, removing the segments of elsif involving the (five) options that are mutually exclusive. It uses List::MoreUtils::firstval . The few other specific invocations are best checked one by one.

There is no use of returning $OPTIONS since it is passed as reference so any changes apply to the original structure (while it's not meant to be changed either). Perhaps you can keep track of whether there were errors and return that if it can be used in the caller, or just return 1 .

This addresses the long elsif chain as asked, and doesn't go into the rest of code. Here is one comment though: There is no need for {%OPTIONS} , which copies the hash in order to create an anonymous one; just use return \%OPTIONS;


Comment on possible multiple conflicting options

This answer as it stands does not print all conflicting options that have been used if there are more than two, as raised by ikegami in comments; it does catch any conflicts so that the run is aborted.

The code is readily adjusted for this. Instead of the code in the if block either

However, one is expected to know of allowed invocations and any listing of conflicts is a courtesy to the forgetful user (or a debugging aid); a usage message is printed as well anyway.

Given the high number of conflicting options the usage message should contain a prominent note on this. Also consider that so many conflicting options may indicate a design flaw.

Finally, this code fully relies on the fact that this processing goes once per run and operates with a handful of options; thus it is not concerned with efficiency and freely uses ancillary data structures.

Speeddymon ,yesterday

Updated the question to clarify. – Speeddymon yesterday

zdim ,yesterday

@Speeddymon Thank you, updated. This brings together checks of those five options which can't go one with another. The remaining few I leave to be checked one by one; "encoding" one or two possibilities in some all-encompassing system would just increase complexity (and may end up less readable). – zdim yesterday

zdim ,yesterday

@Speeddymon Added the missing include, use List::MoreUtils 'firstval' . Edited a little in the meanwhile, as well. – zdim yesterday

Speeddymon ,yesterday

Thank you for the easy to follow example. I went with yours as it was the clearest and contained the least duplicate code. – Speeddymon yesterday

ikegami ,23 hours ago

@Speeddymon, Apparently, it's not clear as you think since you didn't realize if doesn't work. It doesn't mention the error of using -r and -c together if -b is also provided. And why is a hash being used at all? Wasteful and needlessly complex. – ikegami 23 hours ago

simbabque ,yesterday

You can use a dispatch table if there are a lot of options. I would build that table programmatically. It might not be the best option here, but it works and the configuration is more readable than your elsif construct.
use strict;
use warnings;
use Ref::Util::XS 'is_arrayref';    # or Ref::Util

sub create_key {
    my $input = shift;

    # this would come from somewhere else, probably the Getopt config
    my @opts = qw( host bash nic nicName console virtual cmdb
        policyid showcompliant backup backuphistory page );

    # this is to cover the configuration with easier syntax
    $input = { map { $_ => 1 } @{$input} }
        if is_arrayref($input);

    # options are always prefilled with false values
    return join q{}, map { $input->{$_} ? 1 : 0 }
        sort @opts;
}

my %forbidden_combinations = (
    map { create_key( $_->[0] ) => $_->[1] } (
        [ [qw( console virtual )] => q{Cannot use flags -r and -v together} ],
        [ [qw( console cmdb )]    => q{Cannot use flags -r and -d together} ],
        [ [qw( console backup )]  => q{Cannot use flags -r and -b together} ],
        [ [qw( console nic )]     => q{Cannot use flags -r and -n together} ],
    )
);

p %forbidden_combinations; # from Data::Printer

The output of the p function is the dispatch table.

{
    00101   "Cannot use flags -r and -v together",
    00110   "Cannot use flags -r and -n together",
    01100   "Cannot use flags -r and -d together",
    10100   "Cannot use flags -r and -b together"
}

As you can see, we've sorted all the options ascii-betically to use them as keys. That way, you could in theory build all kinds of combinations like exclusive options.

Let's take a look at the configuration itself.

my %forbidden_combinations = (
    map { create_key( $_->[0] ) => $_->[1] } (
        [ [qw( console virtual )] => q{Cannot use flags -r and -v together} ],
        # ...
    )
);

We use a list of array references. Each entry is on one line and contains two pieces of information. Using the fat comma => makes it easy to read. The first part, which is much like a key in a hash, is the combination. It's a list of fields that should not occur together. The second element in the array ref is the error message. I've removed all the recurring elements, like the newline, to make it easier to change how and where the error can be displayed.

The map around this list of combination configuration runs the options through our create_key function, which translates it to a simple bitmap-style string. We assign all of it to a hash of that map and the error message.

Inside create_key , we check if it was called with an array reference as its argument. If that's the case, the call was for building the table, and we convert it to a hash reference so we have a proper map to look stuff up in. We know that the %OPTIONS always contains all the keys that exist, and that those are pre-filled with values that all evaluate to false . We can harness that convert the truthiness of those values to 1 or 0 , which then builds our key.

We will see in a moment why that is useful.

Now how do we use this?

sub HelpMessage { exit; }; # as a placeholder

# set up OPTIONS
my %OPTIONS = (
    host          => q{},
    bash          => 0,
    nic           => 0,
    nicName       => q{},
    console       => 0,
    virtual       => 0,
    cmdb          => 0,
    policyid      => 0,
    showcompliant => 0,
    backup        => 0,
    backuphistory => 0,
    page          => q{},
);

# read options with Getopt::Long ...
$OPTIONS{console} = $OPTIONS{virtual} = 1;

# ... and check for wrong invocations
if ( exists $forbidden_combinations{ my $key = create_key($OPTIONS) } ) {
    warn "ERROR: $forbidden_combinations{$key}\n";
    HelpMessage;
}

All we need to do now is get the $OPTIONS hash reference from Getopt::Long, and pass it through our create_key function to turn it into the map string. Then we can simply see if that key exists in our %forbidden_combinations dispatch table and show the corresponding error message.


Advantages of this approach

If you want to add more parameters, all you need to do is include them in @opts . In a full implementation that would probably be auto-generated from the config for the Getopt call. The keys will change under the hood, but since that is abstracted away you don't have to care.

Furthermore, this is easy to read. The create_key aside, the actual dispatch table syntax is quite concise and even has documentary character.

Disadvantages of this approach

There is a lot of programmatic generation going on for just a single call. It's certainly not the most efficient way to do it.


To take this further, you can write functions that auto-generate entries for certain scenarios.

I suggest you take a look at the second chapter in Mark Jason Dominus' excellent book Higher-Order Perl , which is available for free as a PDF.

Speeddymon ,yesterday

Thank you for the detailed answer. I've updated the question to help clarify how the $OPTIONS hash is setup. Can your example work within the bounds of what I have already, or should I rewrite the whole thing from scratch? – Speeddymon yesterday

simbabque ,yesterday

@Speeddymon yeah, that should work. I see you've got %OPTIONS , and it is always pre-set with values. That's going to be interesting. Let me try. – simbabque yesterday

Speeddymon ,yesterday

Speaking of the HOP book... That was actually what I was using to try to learn and where I was having trouble in applying the concept to my code. :-) I couldn't find a PDF version before, so thank you for the link! – Speeddymon yesterday

simbabque ,yesterday

@Speeddymon I've updated the answer and changed it to match your updated code. I suggest you read the diff first. What I don't like about it yet is that the possible keys are there twice, but that can be solved with some more trickery. I think that would blow up the answer even more, so I didn't do that. – simbabque yesterday

ikegami ,23 hours ago

Doesn't detect the case when -r , -v and -b are provided as an error. – ikegami 23 hours ago

ikegami ,2 days ago

You shouldn't be using elsif here because multiple condition could be true. And since multiple conditions could be true, a dispatch table can't be used. Your code can still be simplified greatly.
my @errors;

push @errors, "ERROR: Host must be provided\n"
   if !defined($OPTIONS{host});

my @conflicting =
   map { my ($opt, $flag) = @$_; $OPTIONS->{$opt} ? $flag : () }
      [ 'console', '-r' ],
      [ 'virtual', '-v' ],
      [ 'cmdb',    '-d' ],
      [ 'backup',  '-b' ],
      [ 'nic',     '-n' ];

push @errors, "ERROR: Can only use one the following flags at a time: @conflicting\n"
   if @conflicting > 1;

push @errors, "ERROR: Can't use flag -p without also specifying -d\n"
   if defined($OPTIONS->{policyid}) && !$OPTIONS->{cmdb};

push @errors, "ERROR: Can't use flag -c without also specifying -d\n"
   if $OPTIONS->{showcompliant} && !$OPTIONS->{cmdb};

push @errors, "ERROR: Can't use flag -s without also specifying -b\n"
   if $OPTIONS->{backuphistory} && !$OPTIONS->{backup};

push @errors, "ERROR: Can't use flag -m without also specifying -n\n"
   if defined($OPTIONS->{nicName}) && !$OPTIONS->{nic};

push @errors, "ERROR: Incorrect number of arguments\n"
   if @ARGV;

usage(@errors) if @errors;

Note that the above fixes numerous errors in your code.


Help vs Usage Error

Calling HelpMessage indifferently in both situations is therefore incorrect.

Create the following sub named usage to use (without arguments) when GetOptions returns false, and with an error message when some other usage error occurs:

use File::Basename qw( basename );

sub usage {
   my $prog = basename($0);
   print STDERR $_ for @_;
   print STDERR "Try '$prog --help' for more information.\n";
   exit(1);
}

Keep using HelpMessage in response to --help , but the defaults for the arguments are not appropriate for --help . You should use the following:

'help' => sub { HelpMessage( -exitval => 0, -verbose => 1 ) },

Speeddymon ,yesterday

I wondered if it would be impossible because of multiple conditions being true, but based on other answers, it seems that it is possible to still build a table and compare... – Speeddymon yesterday

ikegami ,yesterday

What are you talking about? No answer used a dispatch table. All the answers (including mine) used a ( for or map ) loop that performs as many checks as there are conditions. The points of a dispatch table is to do a single check no matter how many conditions there are. Since all conditions can be true, you need to check all conditions, so a dispatch table is impossible by definition. (And that's without even mentioning that the value of a dispatch table should be a code reference or similar (something to dispatch to).) – ikegami yesterday

ikegami ,yesterday

The difference between mine and the others is that mine avoids using an inefficient unordered hash and uses an efficient ordered list instead. (You could place the list in an array if you prefer.) – ikegami yesterday

ikegami ,yesterday

Updated to match updated question. That fact that none of the other answers can be extended for your updated question proves my pointthat trying to put everything into one loop or table just makes things less flexible, longer and more complex. – ikegami yesterday

Speeddymon ,yesterday

In response to the "help" tip -- HelpMessage is defined by GetOpt::Long and reads from the PODs at the end of the file. – Speeddymon yesterday

[Nov 22, 2017] Perl modules

Nov 17, 2017 | perlmonks.com

Discipulus (Monsignor) on Nov 16, 2017 at 09:04 UTC

Re: perl modules

Hello codestroman and welcome to the monastery and to the wonderful world of Perl!

First of all, please, add <c> code tags </c> around your code and output.

Then be sure to have read the standard documentation: perlmod and perlnewmod

Infact a basic Perl module define a package and use Exporter to export functions in the using Perl program.

In my homenode i've collected a lot of links on about module creation

L*

Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

thanos1983 (Priest) on Nov 16, 2017 at 09:17 UTC

Re: perl modules

Hello codestroman

Just to add a minor suggestion here, to the full cover reply of fellow monk Discipulus . It will assist you a lot also to read Simple Module Tutorial

Update: Direct answer to your question can be found here How to add a relative directory to @INC with multiple possible solutions. I would strongly recommend to go through all the articles that all monks proposed.

Hope this helps, BR.

Seeking for Perl wisdom...on the process of learning...not there...yet!

hippo (Abbot) on Nov 16, 2017 at 09:21 UTC

Re: perl modules (Can't locate in @INC)
PLEASE HELP!!

This is a monastery - a place of quite contemplation. The louder you shout the less wisdom shall you receive.

The error message Can't locate dog.pm in @INC is pretty explicit. Either your module file is not called dog.pm in which case, change it or else your file dog.pm is not in any of the directories listed in @INC in which case either move it to one of those directories or else change @INC with use lib .

I also see, despite the lack of formatting in your post that your module doesn't use any namespace. You should probably address that. Perhaps a solid read through Simple Module Tutorial would be a good idea?

Anonymous Monk on Nov 16, 2017 at 09:07 UTC

Re: perl modules

use an absolute pathname in use lib

Anonymous Monk on Nov 16, 2017 at 15:16 UTC

Re: perl modules

Welcome to the language ... and, to the Monastery. The "simple module tutorial" listed above is a very good place to start. Like all languages of its kind, Perl looks at runtime for external modules in a prescribed list of places, in a specified order. You can affect this in several ways, as the tutorials describe. Please read them carefully.

In the Perl(-5) language, this list is stored in a pre-defined array variable called @INC and it is populated from a variety of sources: a base-list that is compiled directly into the Perl interpreter, the PERL5LIB environment-variable, use lib statements, and even direct modification of the variable itself. Perl searches this list from beginning to end and processes (only) the first matching file that it finds.

(Note that, in Perl, the use statement is actually a pragma, or declaration to the compiler, and as such it has many "uses" and a somewhat complicated syntax.)

Corion (Pope) on Nov 16, 2017 at 15:23 UTC

Re^2: perl modules


by Corion (Pope) on Nov 16, 2017 at 15:23 UTC

(Note that, in Perl, the use statement is actually a pragma, or declaration to the compiler, and as such it has many "uses" and a somewhat complicated syntax.)

Please no.

The word "pragma" has a special meaning in Perl, and it is highly confusing to claim that a Perl "keyword" would be a "pragma". use certainly is a keyword and nothing else.

If you mean to say something different, please describe in more words what you want to say.

[Nov 22, 2017] Perl grep array FAQ - How to search an array-list of strings alvinalexander.com

Nov 22, 2017 | alvinalexander.com

Perl grep array FAQ - How to search an array/list of strings By Alvin Alexander. Last updated: June 3 2016 Perl "grep array" FAQ: Can you demonstrate a Perl grep array example? (Related: Can you demonstrate how to search a Perl array?)

A very cool thing about Perl is that you can search lists (arrays) with the Perl grep function. This makes it very easy to find things in large lists -- without having to write your own Perl for/foreach loops.

A simple Perl grep array example (Perl array search)

Here's a simple Perl array grep example. First I create a small string array (pizza toppings), and then search the Perl array for the string "pepper":

# create a perl list/array of strings
@pizzas = qw(cheese pepperoni veggie sausage spinach garlic);

# use the perl grep function to search the @pizzas list for the string "pepper"
@results = grep /pepper/, @pizzas;

# print the results
print "@results\n";

As you might guess from looking at the code, my @results Perl array prints the following output:

pepperoni
Perl grep array - case-insensitive searching

If you're familiar with Perl regular expressions, you might also guess that it's very easy to make this Perl array search example case-insensitive using the standard i operator at the end of my search string.

Here's what our Perl grep array example looks like with this change:

@results = grep /pepper/i, @pizzas;
Perl grep array and regular expressions (regex)

You can also use more complex Perl regular expressions (regex) in your array search. For instance, if for some reason you wanted to find all strings in your array that contain at least eight consecutive word characters, you could use this search pattern:

@results = grep /\w{8}/, @pizzas;

That example results in the following output:

pepperoni
Perl grep array - Summary

I hope this Perl grep array example (Perl array search example) has been helpful. For related Perl examples, see the Related block on this web page, or use the search form on this website. If you have any questions, or better yet, more Perl array search examples, feel free to use the Comments section below.

[Nov 22, 2017] perl - How can I also get an element's index when I grep through an array - Stack Overflow

Nov 22, 2017 | stackoverflow.com

Learn more up vote down vote favorite

Geo ,Jun 10, 2010 at 16:39

Let's say I have this list:
my @list = qw(one two three four five);

and I want to grab all the elements containing o . I'd have this:

my @containing_o = grep { /o/ } @list;

But what would I have to do to also receive an index, or to be able to access the index in grep 's body?

,

my @index_containing_o = grep { $list[$_] =~ /o/ } 0..$#list;  # ==> (0,1,3)

my %hash_of_containing_o = map { $list[$_]=~/o/?($list[$_]=>$_):() } 0..$#list
            # ==> ( 'one' => 0, 'two' => 1, 'four' => 3 )

[Nov 22, 2017] Perl Searching for item in an Array - Stack Overflow

Nov 22, 2017 | stackoverflow.com

Perl: Searching for item in an Array Ask Question up vote down vote favorite 1

Majic Johnson ,Apr 20, 2012 at 4:53

Given an array @A we want to check if the element $B is in it. One way is to say this:
Foreach $element (@A){
    if($element eq $B){
        print "$B is in array A";
    }
}

However when it gets to Perl, I am thinking always about the most elegant way. And this is what I am thinking: Is there a way to find out if array A contains B if we convert A to a variable string and use

index(@A,$B)=>0

Is that possible?

cHao ,Apr 20, 2012 at 4:55

grep { $_ eq $B } @A ? – cHao Apr 20 '12 at 4:55

daxim ,Apr 20, 2012 at 7:06

Related: stackoverflow.com/questions/7898499/ stackoverflow.com/questions/3086874/daxim Apr 20 '12 at 7:06

Nikhil Jain ,Apr 20, 2012 at 5:49

There are many ways to find out whether the element is present in the array or not:
  1. Using foreach
    foreach my $element (@a) {
        if($element eq $b) {
           # do something             
           last;
        }
    }
    
  2. Using Grep:
    my $found = grep { $_ eq $b } @a;
    
  3. Using List::Util module
    use List::Util qw(first); 
    
    my $found = first { $_ eq $b } @a;
    
  4. Using Hash initialised by a Slice
    my %check;
    @check{@a} = ();
    
    my $found = exists $check{$b};
    
  5. Using Hash initialised by map
    my %check = map { $_ => 1 } @a;
    
    my $found = $check{$b};
    

pilcrow ,May 2, 2012 at 19:56

The List::Util::first() example is (potentially) subtly incorrect when searching for false values, since $found will also evaluate false. ( die unless $found ... oops!) List::MoreUtils::any does the right thing here. – pilcrow May 2 '12 at 19:56

yazu ,Apr 20, 2012 at 4:56

use 5.10.1;

$B ~~ @A and say '$B in @A';

brian d foy ,Apr 20, 2012 at 13:07

You have to be very careful with this because this distributes the match over the elements. If @A has an array reference element that contains $B, this will still match even though $B isn't a top level element of @A. The smart match is fundamentally broken for this and many other reasons. – brian d foy Apr 20 '12 at 13:07

obmib ,Apr 20, 2012 at 5:51

use List::AllUtils qw/ any /;
print "\@A contains $B" if any { $B eq $_ } @A;

bvr ,Apr 20, 2012 at 7:43

I would recommend first in this case, as it does not have to traverse whole array. It can stop when item is found. – bvr Apr 20 '12 at 7:43

brian d foy ,Apr 20, 2012 at 13:10

any can stop too because it needs only one element to be true. – brian d foy Apr 20 '12 at 13:10

pilcrow ,May 3, 2012 at 1:38

Beware that first can also return a false value if it finds, e.g., "0", which would confound the example given in this answer. any has the desired semantics. – pilcrow May 3 '12 at 1:38

[Nov 22, 2017] Bitwise operators supported by Perl language

Nov 18, 2017 | www.tutorialspoint.com
Bitwise operator works on bits and perform bit by bit operation. Assume if $a = 60; and $b = 13; Now in binary format they will be as follows − $a = 0011 1100 $b = 0000 1101 ----------------- $a&$b = 0000 1100 $a|$b = 0011 1101 $a^$b = 0011 0001 ~$a = 1100 0011 There are following Bitwise operators supported by Perl language, assume if $a = 60; and $b = 13
S.No. Operator & Description
1 &

Binary AND Operator copies a bit to the result if it exists in both operands.

Example − ($a & $b) will give 12 which is 0000 1100

2 |

Binary OR Operator copies a bit if it exists in eather operand.

Example − ($a | $b) will give 61 which is 0011 1101

3 ^

Binary XOR Operator copies the bit if it is set in one operand but not both.

Example − ($a ^ $b) will give 49 which is 0011 0001

4 ~

Binary Ones Complement Operator is unary and has the efect of 'flipping' bits.

Example − (~$a ) will give -61 which is 1100 0011 in 2's complement form due