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 ;-)

[Nov 22, 2020] remove first and last character of string

Oct 15, 2020 | perlmonks.org

syphilis on Oct 14, 2020 at 02:26 UTC

e: remove first and last character of string

i've thought of using substr but i can't be sure that the number above in quotes will always be the same number of characters

You can use substr() without knowing the number of characters.
To remove the first character of $str: substr($str, 0, 1, '')
To remove the last character of $str : substr($str, -1, 1, '')
Or remove the last character of $str : substr($str, length($str) - 1, '')
Or, just use chop() to remove the last character, as you've already noted.

Cheers,
Rob

rsFalse on Oct 14, 2020 at 06:41 UTC

Re: remove first and last character of string

To delete the first and the last character: for( 1 .. 2 ){ $string = reverse $string; chop $string; } [download]

kcott on Oct 14, 2020 at 09:09 UTC

Re: remove first and last character of string

G'day flieckster ,

"what is the best way to remove the first and last character, or remove the "" from the variable ?" [my emphasis]

If you only need to remove the leading and trailing quotes, and the example data you provided is representative, i.e. no embedded quotes, the easiest and most efficient way to do this would be by using transliteration :

$string =~ y/"//d [download]

Here's a quick, yet complete, command line example:

$ perl -E 'my $x = q{"654321_1111"}; say $x; $x =~ y/"//d; say $x' "654321_1111" 654321_1111 [download]

[Aside: In his book, " Perl Best Practices ", Damian Conway used the term transobliteration to describe this particular usage.]

-- Ken

AnomalousMonk on Oct 14, 2020 at 07:11 UTC

Re^2: remove first and last character of string


by AnomalousMonk on Oct 14, 2020 at 07:11 UTC

It's not clear to me if flieckster intends to deal only with strings like '"foo"' (from which it is clear that 'foo' should be extracted), or if he or she may also be dealing with strings like 'foo' '"foo' 'foo"' 'f"o"o' etc., i.e., strings not having double-quotes at both the start and end of the string.

In the latter case, it should be noted that
qr/^\"(.+)\"$/
will not match and will return an empty list, leaving $got undefined.

Give a man a fish : <%-{-{-{-<

AnomalousMonk on Oct 14, 2020 at 17:17 UTC

Re: remove first and last character of string

As with others who have commented in this thread, it's not clear to me just what flieckster wants to achieve.

If, and it's a big if, the aim is to remove double-quotes only when they are paired at both the start and end of the string and never in any other circumstance, then
qr{ (?| \A " (.*) " \z | (.*)) }xms # needs 5.10+
will do the trick. With this regex,
'""' '""""' '"foo"' '"fo"o"' '"f"o"o"'
become
'' '""' 'foo' 'fo"o' 'f"o"o'
respectively, while strings like
'' '"' '"foo' 'foo"' 'f"oo' 'f"o"o'
are unchanged.

Note that this regex needs Perl version 5.10+ because it uses the (?|...) branch reset regex extension. The regex can be made to work in pre-5.10 versions by removing the (?|...) and adding a grep defined, ... filter to the output of the regex match.

[Oct 15, 2020] automateaching -- part 2- proof of concept

Oct 15, 2020 | perlmonks.org

by Discipulus

on Sep 30, 2020 at 08:45 UTC ( # 11122359 = perlmeditation : print w/replies , xml ) Need Help?? Only Perl can teach Perl
Discipulus Introduction

This is the follow up of Perl Automateaching -- part 1: brainstorming so read it first to have an idea of my intentions even if the pseudocode presented there is not what I currently plan.

I have choosen the name for this project and it will be Perl::Teacher as it is clear and explicative.

This post is a mere proof of concept about Perl teaching and, yes! it can be done! I'd like to be billionaire to hire super skilled perl geeks to develop my idea... but let's say they are all busy at the moment :) so the pupil ( discipulus in Latin) will squeeze his brain and will dress teacher dresses. Contributors are welcome!

In the final form Perl::Teacher will be document oriented, ie: it will analyze perl programs wrote by the pupil in physical files. But in the current proof of concepts various student's attempts are hardcoded into the below program contained in scalars from $work_01 to $work_n and with a $solution_code

Also the final form of Perl::Teacher will be a bit interactive presenting and reviewing assignements and telling small lessons, but for the moment nothing of this is done.

So running the below program you will see a serie of attempts to satisfy the assignemnt and results of tests applied to provided code fragments.

Modify the $debug variable to 1 or 2 to see much more messages.

Proof of concept

Here my efforts up now ( Ignore the warning you'll receive: Having more than one /x regexp modifier is deprecated at .../perl5.24-64b/perl/site/lib/Perl/Critic/Policy/ValuesAndExpressions/RequireInterpolationOfMetachars.pm line 110. beacuse it is a problem of Perl::Critic itself: see resolved issue on github )

use strict; use warnings; use PPI; use PPI::Dumper; use Perl::Critic; use Test::Deep::NoTest; use Data::Dump; my $debug = 0; # 0..2 my $perl_critic_severity = 'gentle'; # 'gentle' 'stern' 'harsh' 'crue + l' 'brutal' # assignemnt print <<'EOP'; Assignement: -Create an array named @letters with 5 elements and fill it with first + 5 letters of the English alphabet -Remove the first element using a list operator and assign it to a sca + lar variable -Remove the last element using a list operator and assign it to a scal + ar variable -Join these two removed elements with a '-' (using single quotes) sign + and assign the result to a scalar named $result NB: All variables have to be lexically scoped NB: each above steps must be accomplished in one statement EOP # solution code my $solution_code = <<'EOC'; use strict; use warnings; my @letters = ('a'..'e'); my $first = shift @letters; my $last = pop @letters; my $result = join '-', $first, $last; EOC # student attempts my $work_01 = <<EOT; need to crash! EOT my $work_02 = <<EOT; # comment: no need to crash! EOT my $work_03 = <<EOT; # comment: no need to crash! use strict; EOT my $work_04 = <<EOT; # comment: no need to crash! use strict; use warnings; EOT my $work_05 = <<'EOT'; use strict; use warnings; my @letters = ('a'..'e'); EOT my %tests = ( # TEST DESCRIPTION # number => anonymous hash (tests will be executed in a sorted + order) # name => # run => send the code to a sub returning 0|1 plus + messages # select_child_of => given a PPI class search each element + of such class # to see if they contain all required el + ements. # returns 0|1 plus messages # class => the class of elements to analyze (all el + ements of such class will be tested) # tests => anonymous array: check children of the c + urrent element to be of the appropriate class # and to hold the desired content (string + or regex can be used) # evaluate_to => optional but only possible if select_child + _of was used: the DPOM fragment # extracted by select_child_of will be chec + k to hold a precise value (at runtime: see below) # hint => # docs => 001 => { name => 'code compiles', run => \&test_compile, # select_child_of ... # evaluate_to ... hint => "comment the line causing crash with a # in fro + nt of it", docs => ['perldoc perlintro', 'https://perldoc.perl.org + /perlintro.html#Basic-syntax-overview'], }, 002 => { name => 'strictures', # run => ... select_child_of => { class => 'PPI::Statement::Include', tests => [ #['PPI::Token::Word', 'use'], ['PPI::Token::Word', qr/^use$/], ['PPI::Token::Word', 'strict'] ], }, # evaluate_to ... hint => "search perlintro for safety net", docs => ['https://perldoc.perl.org/perlintro.html#Safet + y-net'], }, 003 => { name => 'warnings', # run => ... select_child_of => { class => 'PPI::Statement::Include', tests => [ ['PPI::Token::Word', 'use'], #['PPI::Token::Word', qr/^use$/], ['PPI::Token::Word', 'warnings'] ], }, # evaluate_to ... hint => "search perlintro for safety net", docs => ['https://perldoc.perl.org/perlintro.html#Safet + y-net'], }, 004 => { name => 'array creation', select_child_of => { class => 'PPI::Statement::Variable', tests => [ ['PPI::Token::Word', 'my'], ['PPI::Token::Symbol', '@letters'], ['PPI::Token::Operator', '='], ], }, evaluate_to => [ ('a'..'e') ], hint => "search perlintro basic variable types", docs => ['https://perldoc.perl.org/perlintro.html#Perl- + variable-types'], }, 005 => { name => 'first element of the array', select_child_of => { class => 'PPI::Statement::Variable', tests => [ ['PPI::Token::Word', 'my'], ['PPI::Token::Symbol', qr/\$[\S]/], ['PPI::Token::Operator', '='], ['PPI::Token::Word', 'shift'], ['PPI::Token::Symbol', '@letters'], ], }, evaluate_to => \'a', hint => "search functions related to real arrays", docs => ['https://perldoc.perl.org/5.32.0/perlfunc.html + #Perl-Functions-by-Category'], }, 006 => { name => 'last element of the array', select_child_of => { class => 'PPI::Statement::Variable', tests => [ ['PPI::Token::Word', 'my'], ['PPI::Token::Symbol', qr/\$[\S]/], ['PPI::Token::Operator', '='], ['PPI::Token::Word', 'pop'], ['PPI::Token::Symbol', '@letters'], ], }, evaluate_to => \'e', hint => "search functions related to real arrays", docs => ['https://perldoc.perl.org/5.32.0/perlfunc.html + #Perl-Functions-by-Category'], }, 007 => { name => 'final result', select_child_of => { class => 'PPI::Statement::Variable', tests => [ ['PPI::Token::Word', 'my'], ['PPI::Token::Symbol', '$result'], ['PPI::Token::Operator', '='], ['PPI::Token::Word', 'join'], ['PPI::Token::Quote::Single', "'-'"], ['PPI::Token::Operator', ','], ['PPI::Token::Symbol', qr/^\$[\S]/], ['PPI::Token::Operator', ','], ['PPI::Token::Symbol', qr/^\$[\S]/], ], }, evaluate_to => \'a-e', hint => "search functions related to strings", docs => ['https://perldoc.perl.org/5.32.0/perlfunc.html + #Perl-Functions-by-Category'], }, ); # student's attempts examination foreach my $code ( $work_01, $work_02, $work_03, $work_04, $work_05, $ + solution_code){ $code = PPI::Document->new( \$code ); print "\n# START of provided code:\n",$code=~s/^/| /gmr,"# END of + provided code\n# TESTS:\n"; PPI::Dumper->new($code)->print if $debug > 1; my $passed_tests; foreach my $test (sort keys %tests){ print "DEBUG: starting test $test - $tests{ $test }{ name }\n" + if $debug; # if run defined my $run_result; my $run_msg; if ( exists $tests{ $test }{ run } ){ ($run_result, $run_msg) = $tests{ $test }{ run }->( $code + ); if ( $run_result ){ print "OK test [$tests{ $test }{ name }]\n"; $passed_tests++; # next test next; } else{ $run_msg =~ s/\n//; print "FAILED test [$tests{ $test }{ name }] because: + $run_msg\n"; if ( $tests{ $test }{ hint } ){ print "HINT: $tests{ $test }{ hint }\n"; } if ( $tests{ $test }{ docs } ){ print map {"DOCS: $_\n"} @{$tests{ $test }{ docs } + } ; } last; } } # select_child_of defined my $candidate_pdom; my $select_child_of_msg; if ( exists $tests{ $test }{ select_child_of } ){ ($candidate_pdom, $select_child_of_msg) = select_child_of( pdom => $code, wanted_class => $tests{ $test }{ select_child_of } + { class }, tests => $tests{ $test }{ select_child_of }{ tests + } ); } # also evaluation is required if( $candidate_pdom and exists $tests{ $test }{ evaluate_to } + ){ my ($evauleted_pdom, $eval_msg) = evaluate_to ( $candidate_pdom, $tests{ $test }{ evalua + te_to } ); if($evauleted_pdom){ print "OK test [$tests{ $test }{ name }]\n"; $passed_tests++; # jump to next test next; } else{ print "FAILED test [$tests{ $test }{ name }] becau + se: $eval_msg\n"; if ( $tests{ $test }{ hint } ){ print "HINT: $tests{ $test }{ hint }\n"; } if ( $tests{ $test }{ docs } ){ print map {"DOCS: $_\n"} @{$tests{ $test }{ do + cs }} ; } } } elsif( $candidate_pdom ){ print "OK test [$tests{ $test }{ name }]\n"; $passed_tests++ ; # jump to next test next; } else{ print "FAILED test [$tests{ $test }{ name }] because: $sel + ect_child_of_msg\n"; if ( $tests{ $test }{ hint } ){ print "HINT: $tests{ $test }{ hint }\n"; } if ( $tests{ $test }{ docs } ){ print map {"DOCS: $_\n"} @{$tests{ $test }{ docs }} ; } # if one test breaks end the testing loop last; } } # all tests passed if ( $passed_tests == scalar keys %tests ){ print "\nALL tests passed\n"; my $critic = Perl::Critic->new( -severity => $perl_critic_sev + erity ); my @violations = $critic->critique($code); if ( @violations ){ print "Perl::Critic violations (with severity: $perl_criti + c_severity):\n"; print @violations; } else{ print "No Perl::Critic violations using severity level: $p + erl_critic_severity\n"; } } print "\n\n"; } ################################ # TESTS ################################ sub evaluate_to{ my $pdom = shift; # passed by reference my $expected_value = shift; ############################### # VERY DIRTY TRICK - START ############################### # only last element is returned in string evaluation # so the below code cuts the parent where the current # pdom is found. so the current statement will be the # last one of the whole code (parent) and its value # returned by the string evaluation # (probably I'll need to redirect STDOUT in this scope) # # NB this will fail for multiline statements! my $pdom_parent = $pdom->parent; my @lines_od_code = split/\n/,$pdom_parent->content; if ( $debug > 1 ){ print "ORIGINAL CODE:\n"; dd @lines_od_code; print "FOUND current PDOM element at line: ", $pdom->line_numb + er, "\n"; print "CUTTING code at line: ", $pdom->line_number, "\n"; dd @lines_od_code[0..$pdom->line_number-1] } $pdom = PPI::Document->new( \join"\n",@lines_od_code[0..$pdom->lin + e_number-1] ); ############################### # VERY DIRTY TRICK - END ############################### { local $@; my $got; # we expect a scalar ref if ( ref $expected_value eq 'SCALAR' ){ $got = \eval $pdom ; } # we expect an array ref elsif ( ref $expected_value eq 'ARRAY' ){ $got = [ eval $pdom ]; } # we expect a hash ref elsif ( ref $expected_value eq 'HASH' ){ $got = { eval $pdom }; } # we expect a regexp ref elsif ( ref $expected_value eq 'Regexp' ){ $got = eval $pdom; $got = qr/$got/; } # Not a reference else{ $got = eval $pdom; } # check to be the same type if ( ref $expected_value ne ref $got ){ return (0, "got and expected values are not of the same ty + pe") } else{ print "DEBUG: OK both got and expected are of the same typ + e: ", ref $got,"\n" if $debug; } if ( eq_deeply( $got, $expected_value ) ){ if ( $debug > 1 ){ print "DEBUG: OK both got and expected hold sa + me content: "; dd $got; } return ($pdom, "expected value found for the expre + ssion [$pdom]"); } else{ if ( $debug ){ print "GOT: ",ref $got,"\n"; dd $got; print "EXPECTED: ",ref $expected_value,"\n"; dd $expected_value; #print "PARENT: "; PPI::Dumper->new( $pdom->parent )-> + print; } return (0, "wrong value of the expression [$pdom]") } } } sub select_child_of{ my %opt = @_; my $pdom_fragments = $opt{ pdom }->find( $opt{ wanted_class } ); return (0, "no element found of the correct type") unless $pdom_fr + agments; foreach my $pdom_candidate ( @$pdom_fragments ){ print "DEBUG: checking fragment: [$pdom_candidate]\n" if $debu + g; my $expected_ok; foreach my $test ( @{$opt{ tests }} ){ my ($class, $content) = @$test; print "DEBUG: testing for class [$class] and content [$con + tent]\n" if $debug; if ( $pdom_candidate->find( sub { $_[1]->isa($class) and ( ref $content eq 'R + egexp' ? ( $_[1]->content = + ~ /$content/ ) : ( $_[1]->content e + q $content ) ) } ) ){ $expected_ok++; #print "DEBUG FOUND: [",ref $_[1],"] [",$_[1]->content + ,"]\n"; print "DEBUG: OK..\n" if $debug; if ( $expected_ok == scalar @{$opt{ tests }} ){ print "DEBUG: found a good candidate: [$pdom_candi + date]\n" if $debug; return ( $pdom_candidate, "found expected code in: + [$pdom_candidate]" ) } } else{ print "DEBUG: FAIL skipping to next fragment of co + de\n" if $debug; last; } } } #FAILED return (0,"element not found") } sub test_compile{ my $code = shift; { local $@; eval $code; if ( $@ ){ # print "\$@ = $@"; return (0, $@, "Comment the line with a # in front of it", + "perlintro" ); } else { # $code instead of 1?????? return (1, "code compiles correctly"); } } } [download] Implementation (current)

As you can see there is a lot PPI stuff but not exclusively. Tests are execuded in order from 001 to 00n and if a test fails the current mini program is rejected.

Each test can contain different steps, the first one being the optional run that simply sends the current code to a sub: this preliminary, optional test passes if the sub returns 1 and fails otherwise. Here it is used only to check if the program compiles ( see below for future ideas ).

The second step of a test is select_child_of and it expects a PPI class name and a serie of subtests. Each PPI element of the specified PPI class, for example PPI::Statement::Variable (a variable declaration) will be processed to see if they contains PPI elemnts which satisfy all subtests. The first PPI element passing all subtests is returned by select_child_of and becomes a candidate for further inspections.

Infact if evaluate_to is also specified, the current PPI element is, take a deep breath, keep calm, string evaluated to see if it holds the wanted value. And hic sunt leones or here are dragons because eval only returns the last statement value. Search the code above for the string dirty trick to see my workaround. For me it is a genial solution, but wait, I'm the guy who string eval'ed entire CPAN.. :) so improvements are warmly welcome.

This form of testing is a proof of concepts: is not the final form of the testing framework needed by Perl::Teacher

When a miniprogram passes all tests it is evaluated by Perl::Critic to give more hints to the student. Eventual policy violations will not make the program to be marked as wrong, but are just presented as suggestions.

A note about flexibilty: looking carefully at the assignement you will notice that @letters and $result are constraints. Not the same for the intermediate scalars containing the first element and the last one.

Implementation (future) module design The main Perl::Teacher module will provide only a framework to produce courses. The $teacher will load or create a configuration will have methods to deal with the student's input and to emit messages, but the main activity will be to load and follow courses plugins of the class Perl::Teacher::Course

In my idea the course creator will publish Perl::Teacher::Course::EN::BasicVariables or Perl::Teacher::Course::IT::RegexIntroduzione all being child of the main Perl::Teacher::Course class. These courses have to be pluggable to the $teacher object ( Module::Pluggable probably but I have to investigate it further)

Each course will contain a serie of lessons published a sub modules, as in Perl::Teacher::Course::EN::BasicVariables::01_strings , ..::02_lists etc.

Yes I know: very long names.. but this will ensure a clarity of intent and of usage, in my opinion.

( update October 14 2020 see the related question Module design for loadable external modules containing data )

lessons

Each lesson will contain an ordered serie of optional elements: zero one or more assignement , multiple test elements possibly interleaved by one or more discourse and direct question .

So a possible flow can be:

01 - discourse - introduction to the lesson 02 - discourse - more words 03 - assignement 04 - test 05 - test - more test 06 - test - test test ( block until all tests are ok ) 07 - discourse - explain and add a task 08 - assignement - the main assignement is updated 09 - test 10 - test - more test 11 - test - test test ( block until all tests are ok ) 12 - question 13 - question 14 - discourse - explaining answers ... nn - discourse - TIMTOWTDI nn - discourse - see also [download]

Suggestions on module design are warmly welcome, but i want to keep it as simple as possible, not spawning objects for everything.

tests

Tests presented in the above code are too semplicistics to cover each teaching activity. I need beside positive tests also negative ones for example to prevent the use of modules, or all modules but one, to prevent external program execution and so on. Theese tests will be quite on success and will emit messages only on failure: "dont do this!".

I can use Test::Script to add tests about correct overall syntax check, behaviour of STDOUT and STDERR given different arguments and so on.

Then Perl::Teacher will provide its own tests like ones presented above: evaluate_to ( evaluate_at is probably a better name as it eval the code at a certain line), is dirty but it seems to me a viable option not so risky given the super small and controlled environment. I also plan a method named evaluate_subs which will grab al subs to test them.

I have to mix all this features in a clean and easy to use interface. Suggetions are welcome.

student interaction

During a lesson the student must have the possibility to review the current assignement, to receive hints and be pointed to relevant documentation. Part of this is roughly done in the presented code using hints and docs embedded in tests. Can be and must be improved.

I like to add a TIMTOWTDI discourse at the end of each lesson showing more ways to accomplish, even if not in the very same way, the assignement.

Every output, comprensive of examined code, errors and hints, emitted during 03_array_manipulation must be saved into a 03_array_manipulation.history file so that the student can review the whole lesson including errors commited and pitfalls and the solution alongside different approaches to the same problem. Passing the time this becomes a good source of knoweledge.

further ideas

Testing standalone scripts is an idea haunting me since years. Modulino is an approach. I can be mad enough to take the original PDOM of a given program, then save all subs and use PPI method prune to delete them from the PDOM, then wrap the rest into a new main_original_program sub, add it to a new PDOM along with all previously saved subs. Then I could do the obtained file and test it nicely. A lot of cut 'n paste and probably error prone, but can be a path to explore.

I'd like also my Perl::Teacher to be as much possible input/output agnostic: implement a way to interact with the console leaving open the possibility to be used by a web interface too: how to do this?

I'd like to ear your opinions about this project, sugesstions on module design and implementation of its parts, comments to the above proof concepts and everything you want to share.

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Tux on Sep 30, 2020 at 13:29 UTC

Re: automateaching -- part 2: proof of concept

Feel free to use in the TIMTOWTDI section :)

Assignment should clearly state capitals or lower case. (assumed lower case below).

This was too much of "I could not rest" to resist:

Read more... (8 kB)
Enjoy, Have FUN! H.Merijn

Discipulus on Oct 01, 2020 at 09:24 UTC

Re^2: automateaching -- part 2: proof of concept


by Discipulus on Oct 01, 2020 at 09:24 UTC

Tux ,

Thanks for sharing your TIMTOWTDIness :)

Taking it seriously it demonstrate an important concept: learning is a path to follow, possibly alongside a teacher. Many of us can produce ten different ways to satisfy an assignment using perl. But this is not the point.

As you noticed (lack of lower case specification for the array and the costraint of a single quote for the dash) it is very important to be clear in the assignement, making it also pedantic, and to be sure it imply the usage of already presented elements.

A teacher must introduce concepts and verify how much students have incorporated them.

Teaching, at first, is dedicated to fill ignorant's gap with notions and concepts (then teach how to learn and how to think, but is not my goal).

So a course (in general but also mines) starts with assumed ignorance in one field, and step by step introduces elements and tests the overall students understanding.

To produce PPI tests making all your example to be verified is an immane task, not worth even to plan. While teaching or learning the appropriate virtue is patience not hubris infact to learn is fondamental to recognize somethig superior who teach you.

So I can add this note to my Perl::Teacher project:

about assignements: -be sure to imply only already introduced elements, possibly refering + to the lesson where they were discussed -in the hints section put reminders to previous lessons -be pedantic in the assignement -possibly show up what was expected by tests when datastructures are i + nvolved (this can clarify an assignement) [download]

Tux !! out of the classroom!! :)

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Replies are listed 'Best First'.

[Oct 15, 2020] How to Hire a Great Perl Developer

Oct 15, 2020 | www.toptal.com

References are used frequently and extensively in Perl code. They're very important for a Perl web developer to understand, as the syntax of element access changes depending on whether you have a reference or direct access.

Q: In Perl, how do you initialize the following?

Furthermore, how would you change an array to an array reference, a hash to a hash reference, and vice versa? How do you access elements from within these variables?

A: The use of hash and array references is a pretty basic concept for any experienced Perl developer, but it may syntactically trip up some newer Perl developers or developers who never really grasped the underlying basics. Initializing an Array:
my @arr = (0, 1, 2);

An array is initialized with an @ symbol prefixed to the variable name, which denotes the variable type as an array; its elements are placed in parentheses.

Initializing an Array Reference:
my $arr_ref = [0, 1, 2];

With an array reference, you use the $ symbol, which denotes 'scalar', and the elements are placed in square brackets. The reference isn't specified as an array, just as a scalar, so you have to be careful to handle the variable type appropriately.

With hashes, the syntax is similar.

Initializing a Hash:
my %hash = (0 => 'First', 1 => 'Second', 2 => 'Third');

Just as with an array, the elements of a hash are defined with parentheses, but since the variable is a hash, it's prefixed with a % .

Initializing an Array Reference:
my $hash_ref = {0 => 'First', 1 => 'Second', 2 => 'Third'};

Like an array reference, a hash reference variable is prefixed with a $ , but the elements are placed in curly braces.

Referencing a Hash or an Array

Referencing an array or hash is pretty straightforward. In Perl, a backslash in front of a variable will return the reference to it. You should expect something like the following:

my $arr_ref = \@arr;

my $hash_ref = \%hash;
Dereferencing

Dereferencing a referenced variable is as easy as reassigning it with the appropriate variable identifier. For example, here's how you would dereference arrays and hashes:

my @arr = @$arr_ref;

my %hash = %$hash_ref;
Accessing Elements

The differences between accessing elements of these variable types and their reference versions is another area where amateur developers may get tripped up.

# to access an element of an array
my $element = $arr[0];

Notice that for an array you are not using the @ prefix but rather the $ to denote a scalar, which is the type returned when accessing any element of an array. Accessing the elements of an array reference, a hash, and a hash reference follows a similar syntax:

# to access an element of an array reference
my $element = ${$array_ref}[0];


# to access an element of a hash
my $element = $hash{0};


# to access an element of a hash reference
my $element = $hash_ref->{0};

[Oct 15, 2020] Perl - Breakpoints of a Debugger

Oct 15, 2020 | www.geeksforgeeks.org
DB<15> b valuedir

This creates a breakpoint at the very first executable statement of the subroutine valuedir.

b-command can also be used to halt a program only when a specified condition meets.
For example, below mentioned command tells the debugger to halt when it is about to execute line 12 and the variable $vardir is equal to the null string:

DB<15> b 12 ($vardir eq "")

Any legal Perl conditional expression can be specified with the b statement.

[Oct 10, 2020] Doesn't Perl include current directory in @INC by default?

Jan 01, 2017 | stackoverflow.com

Ask Question Asked 3 years ago Active 2 years ago Viewed 6k times

https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html Report this ad


Stephen , 2017-10-03 16:52:57

17 7

I have never fully understood Perl's resolution of package names, but I always assumed that the following should always work, assuming you are executing myscript.pl from within the directory that contains it:

myscript.pl (contains the following statement: use Class1::Class2::Class3)
Class1/
    Class2/
        Class3.pm (contains the following package declaration: package Class1::Class2::Class3;)

However, this is not working in my code because Class3.pm cannot be located. Looking at @INC, it does not include the current directory, only various directories of my Strawberry Perl installation.

What is the recommended way to solve this? I suppose I could modify @INC, or I could start using FindBin, but I'm not sure which is best. I have inherited this code and am simply migrating it to a new location, but it doesn't look like the old code needed either such solution (I could be wrong, still looking...) perl share edit follow edited Nov 21 '17 at 15:50 ikegami 308k 14 14 gold badges 213 213 silver badges 452 452 bronze badges asked Oct 3 '17 at 16:52 Stephen 5,308 5 5 gold badges 34 34 silver badges 66 66 bronze badges

> ,

add a comment 3 Answers Active Oldest Votes

ikegami ,

30

Perl doesn't search the current directory for modules or the script's directory for modules, at least not anymore. The current directory was removed from @INC in 5.26 for security reasons.

However, any code that relies on the current directory being in @INC was buggy far before 5.26. Code that did so, like yours, incorrectly used the current directory as a proxy for the script's directory. That assumption is often incorrect.

To tell Perl to look in the script's directory for modules, use the following:

use FindBin 1.51 qw( $RealBin );
use lib $RealBin;

or

use Cwd qw( abs_path );
use File::Basename qw( dirname );
use lib dirname(abs_path($0));
share edit follow edited Oct 4 '18 at 8:27 answered Oct 3 '17 at 17:39 ikegami 308k 14 14 gold badges 213 213 silver badges 452 452 bronze badges

ikegami ,

A tangential question, but why $RealBin and not just $Bin ? Does having the links resolved give us any benefit here, or have you used it here just a general good practice? – sundar - Reinstate Monica Apr 9 '18 at 12:19

melpomene , 2017-10-03 17:00:02

9

Having . (the current directory) in @INC was removed in 5.26 for security reasons ( CVE-2016-1238 ). Some Linux distributions have backported the change, so you might run into this problem even if you're using e.g. 5.24. share edit follow edited Oct 3 '17 at 17:44 answered Oct 3 '17 at 17:00 melpomene 77.6k 6 6 gold badges 63 63 silver badges 117 117 bronze badges

melpomene ,

@ikegami Oh, interesting. I didn't know FindBin was fixed. It did search $PATH until version 1.51, released with perl 5.16. – melpomene Oct 3 '17 at 17:42

> ,

7

Perl 5.26 removed having the current working directory in @INC as a security measure.

It's explained in the 5.26 perldelta notes .

[Oct 09, 2020] Doesn't Perl include current directory in @INC by default?

Jan 01, 2017 | stackoverflow.com

Ask Question Asked 3 years ago Active 2 years ago Viewed 6k times

https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html Report this ad


Stephen , 2017-10-03 16:52:57

17 7

I have never fully understood Perl's resolution of package names, but I always assumed that the following should always work, assuming you are executing myscript.pl from within the directory that contains it:

myscript.pl (contains the following statement: use Class1::Class2::Class3)
Class1/
    Class2/
        Class3.pm (contains the following package declaration: package Class1::Class2::Class3;)

However, this is not working in my code because Class3.pm cannot be located. Looking at @INC, it does not include the current directory, only various directories of my Strawberry Perl installation.

What is the recommended way to solve this? I suppose I could modify @INC, or I could start using FindBin, but I'm not sure which is best. I have inherited this code and am simply migrating it to a new location, but it doesn't look like the old code needed either such solution (I could be wrong, still looking...) perl share edit follow edited Nov 21 '17 at 15:50 ikegami 308k 14 14 gold badges 213 213 silver badges 452 452 bronze badges asked Oct 3 '17 at 16:52 Stephen 5,308 5 5 gold badges 34 34 silver badges 66 66 bronze badges

> ,

add a comment 3 Answers Active Oldest Votes

ikegami ,

30

Perl doesn't search the current directory for modules or the script's directory for modules, at least not anymore. The current directory was removed from @INC in 5.26 for security reasons.

However, any code that relies on the current directory being in @INC was buggy far before 5.26. Code that did so, like yours, incorrectly used the current directory as a proxy for the script's directory. That assumption is often incorrect.

To tell Perl to look in the script's directory for modules, use the following:

use FindBin 1.51 qw( $RealBin );
use lib $RealBin;

or

use Cwd qw( abs_path );
use File::Basename qw( dirname );
use lib dirname(abs_path($0));
share edit follow edited Oct 4 '18 at 8:27 answered Oct 3 '17 at 17:39 ikegami 308k 14 14 gold badges 213 213 silver badges 452 452 bronze badges

ikegami ,

A tangential question, but why $RealBin and not just $Bin ? Does having the links resolved give us any benefit here, or have you used it here just a general good practice? – sundar - Reinstate Monica Apr 9 '18 at 12:19

melpomene , 2017-10-03 17:00:02

9

Having . (the current directory) in @INC was removed in 5.26 for security reasons ( CVE-2016-1238 ). Some Linux distributions have backported the change, so you might run into this problem even if you're using e.g. 5.24. share edit follow edited Oct 3 '17 at 17:44 answered Oct 3 '17 at 17:00 melpomene 77.6k 6 6 gold badges 63 63 silver badges 117 117 bronze badges

melpomene ,

@ikegami Oh, interesting. I didn't know FindBin was fixed. It did search $PATH until version 1.51, released with perl 5.16. – melpomene Oct 3 '17 at 17:42

> ,

7

Perl 5.26 removed having the current working directory in @INC as a security measure.

It's explained in the 5.26 perldelta notes .

[Oct 09, 2020] Basic BLOCKs

perlsyn - Perldoc Browser

A BLOCK by itself (labeled or not) is semantically equivalent to a loop that executes once. Thus you can use any of the loop control statements in it to leave or restart the block. (Note that this is NOT true in eval{} , sub{} , or contrary to popular belief do{} blocks, which do NOT count as loops.) The continue block is optional.

The BLOCK construct can be used to emulate case structures.

SWITCH: {
    if (/^abc/) { $abc = 1; last SWITCH; }
    if (/^def/) { $def = 1; last SWITCH; }
    if (/^xyz/) { $xyz = 1; last SWITCH; }
    $nothing = 1;
}

You'll also find that foreach loop used to create a topicalizer and a switch:

SWITCH:
for ($var) {
    if (/^abc/) { $abc = 1; last SWITCH; }
    if (/^def/) { $def = 1; last SWITCH; }
    if (/^xyz/) { $xyz = 1; last SWITCH; }
    $nothing = 1;
}

Such constructs are quite frequently used, both because older versions of Perl had no official switch statement, and also because the new version described immediately below remains experimental and can sometimes be confusing.

[Oct 03, 2020] Setting PERL5LIB

Jan 01, 2011 | stackoverflow.com

Asked 9 years, 7 months ago


CMS , 2011-03-02 12:31:46

9 1

Can I set PERL5LIB in a separate script and call that script in other scripts? How do I do it? And how would it affect the script in which it is used?

Thanks. perl share improve this question follow asked Mar 2 '11 at 12:31 CMS 113 1 1 gold badge 1 1 silver badge 6 6 bronze badges

add a comment 5 Answers Active Oldest Votes

Eugene Yarmash ,

7

Setting PERL5LIB at runtime will not affect Perl's search path. You need to export the variable before executing the interpreter.
Alternatively you can modify @INC at compile time (also possible to do in a separate script/module):

BEGIN { unshift @INC, "/path/to/dir" }

This is what the lib pragma does. share improve this answer follow edited Mar 2 '11 at 14:35 answered Mar 2 '11 at 12:55 Eugene Yarmash 112k 29 29 gold badges 251 251 silver badges 316 316 bronze badges

Mark ,

This doesn't work for me, I think because the PERL5LIB environment variable is processed by the interpreter before the script is executed, so @INC isn't modified. – Mark Mar 2 '11 at 13:25

Mark , 2011-03-02 13:11:54

4

You'd do this via 'use lib' rather than manipulating the environment:

use lib '/home/perl5';

That could be in a separate file that you 'require' in. share improve this answer follow edited Mar 2 '11 at 13:24 answered Mar 2 '11 at 13:11 Mark 431 3 3 silver badges 6 6 bronze badges

> ,

add a comment

zrajm , 2014-05-20 11:05:43

1

PERL5INC is a shell environment variable, so you wouldn't set it inside your Perl program (normally) but instead specify it before invoking Perl. The below is a shell command where I've used PERL5LIB to instruct prove to find a Perl module residing in ~/OnePop :

$ PERL5LIB=~/OnePop prove -l t
... PERL5LIB is unset here ....

When a command is preceded by a variable assignment like this, the shell sets and exports the variable ( PERL5LIB ) to that command, but after that the variable will be unset again. You can also set the variable in the shell, so that all subsequent commands will inherit it.

$ export PERL5LIB=~/OnePop
...
$ prove -l t
... PERL5LIB continues to be set here ...

If you forget the export keyword in the above example (i.e. assigns the value using PERL5LIB=~/OnePop on a separate line) the variable will be set in the shell, but it will not be inherited by any commands you run (meaning that prove will not be able to see it).

Finally, if you wanted to set the environment PERL5LIB variable from inside a Perl program you'd have to write it like this:

$ENV{PERL5LIB} = glob("~/OnePop");   # glob() expands the tilde
system(qw( prove -l t ));

Though, as other have pointed out, if you want to specify the include path from inside Perl it is easier/better to use use lib $PATH . share improve this answer follow answered May 20 '14 at 11:05 zrajm 1,149 1 1 gold badge 11 11 silver badges 18 18 bronze badges

> ,

add a comment

bot403 , 2011-03-02 14:44:36

0

PERL5INC is an environment variable. Environment variables are only inherited from parents to their children and can't (easily) be set the other way around. If you want to store extra search paths in an external file I suggest you make it a simple list of paths and write a simple loop to read each path from the file and manipulate @INC in the current process. If you want this to be done early at compile time you'll have to use a BEGIN {} block.

For example

BEGIN{
  open(INCFILE,"<","my.inc.file") or die($!);
  foreach(<INCFILE>){
    push @INC,$_;
  }
  close(INCFILE);
}
share improve this answer follow edited Mar 27 '17 at 11:00 Donal Fellows 115k 17 17 gold badges 126 126 silver badges 190 190 bronze badges answered Mar 2 '11 at 14:44 bot403 1,923 13 13 silver badges 14 14 bronze badges

> ,

add a comment

> ,

0 Alternative to PERL5LIB:

You could instead install the latest version of Perl 5 available (in a non-system location, of course). After you have used a module file or done whatever is necessary to make the new perl and cpan executables visible to your shell, you can use cpan to install all the modules you need. I have sometimes done this for individual applications in a similar vein to using Python Virtual Environments.

[Oct 01, 2020] smartmatch - Perl 5.20 and the fate of smart matching and given-when

Jan 01, 2013 | stackoverflow.com

Evan Carroll , 2013-06-04 20:37:24

63 5

I just installed Perl 5.18, and I get a lot of warnings like this,

given is experimental at .\[...].pl line [...].
when is experimental at .\[...].pl line [...].
Smartmatch is experimental at C:/strawberry/perl/site/lib/[...] line [...].

Looking into these warnings -- which I've never heard mentioned anywhere -- I was only able to find this in two places,

The Perl Delta still does the most to give mention as to what's happening with those features, it's halfway down buried in the pod,

Smart match, added in v5.10.0 and significantly revised in v5.10.1, has been a regular point of complaint. Although there are a number of ways in which it is useful, it has also proven problematic and confusing for both users and implementors of Perl. There have been a number of proposals on how to best address the problem. It is clear that smartmatch is almost certainly either going to change or go away in the future. Relying on its current behavior is not recommended. Warnings will now be issued when the parser sees ~~, given, or when.

I'm confused at how the most significant change in Perl in the past 10 years could be pulled. I've started using given , when , and smartmatch all over the place. Is there any more information about these futures? How is anyone finding them "confusing?" How are these features likely to change? Is there a plan to implement these features with a module? perl smartmatch share improve this question follow edited Aug 23 at 19:21 HoldOffHunger 7,890 4 4 gold badges 44 44 silver badges 85 85 bronze badges asked Jun 4 '13 at 20:37 Evan Carroll 59.4k 37 37 gold badges 193 193 silver badges 316 316 bronze badges

ikegami ,

Wrong file. You have 5.18, so read the perldelta for 5.18. metacpan.org/module/RJBS/perl-5.18.0/pod/ domm.plix.at/perl/2013_05_given_smartmatch.htmldaxim Jun 4 '13 at 20:40

ikegami ,

37

There are problems with the design of smart-matching. The decision of what any given TYPE ~~ TYPE should do is most often unobvious, inconsistent and/or disputed. The idea isn't to remove smart matching; it's to fix it.

Specifically, ~~ will be greatly simplified, as you can see in a proposal by the 5.18 pumpking. Decisions as to how two things should match will be done with helpers such as those that already exist in Smart::Match .

... ~~ any(...)

Much more readable, much more flexible (fully extensible), and solves a number of problems (such as "When should X be considered a number, and when should it be considered a string?"). share improve this answer follow edited Jul 3 '13 at 20:23 answered Jun 5 '13 at 2:25 ikegami 308k 14 14 gold badges 212 212 silver badges 451 451 bronze badges

Joel Berger ,

Wow, I hadn't seen Smart::Match! This is aweome! leont++ – Joel Berger Jun 5 '13 at 2:42

Joel Berger , 2013-06-05 03:19:07

21

Some insights might be gained by reading rjbs's proposed changes to smartmatch . He is the pumpking (Perl release manager) after all, so his comments and his view of the future is more relevant than most. There is also plenty of community comment on the matter, see here for instance. The 'experimental' status is in effect because, since things are likely to change in the future, it is responsible to inform users of that fact, even if we don't know what those changes will be. share improve this answer follow edited Jun 5 '13 at 3:40 answered Jun 5 '13 at 3:19 Joel Berger 19.5k 4 4 gold badges 45 45 silver badges 99 99 bronze badges

> ,

add a comment

raina77ow ,

9

Well, that's what's said in the description of the patch that downgraded this set of features to experimental:

The behavior of given/when/~~ are likely to change in perl 5.20.0: either smart match will be removed or stripped down. In light of this, users of these features should be warned. A category "experimental::smartmatch" warning should be issued for these features when they are used.

So whil you can indeed turn these warnings off, with something like this ( source ):

no if $] >= 5.018, warnings => "experimental::smartmatch";

... it's just turning your eyes off the problem. share improve this answer follow answered Jun 4 '13 at 20:43 raina77ow 86.7k 10 10 gold badges 171 171 silver badges 201 201 bronze badges

tjd ,

It's not about how to turn these warnings off, it's about what's wrong with Smartmatch/given/when and how will they be remedying the problem. The roadmap is just "change ahead" with no certainty of direction. – Evan Carroll Jun 4 '13 at 20:48

[Oct 01, 2020] ldami- Perl smartmatch - what now -

Oct 01, 2020 | ldami.blogspot.com

Monday, June 23, 2014 Perl smartmatch : what now ? Sorry to wake up an old discussion, but ... does anybody have a clear idea of what is going to happen to smartmatch ?

Our team maintains dozens of internal applications and modules containing "given/when" and smartmatch statements. Most of this code was written between 2007 and 2012 -- remember, at that time smartmatch was an official feature, never mentioned as being "experimental", so we happily used it in many places. The reasons for using smartmatch were quite modest :

[Oct 01, 2020] P5P update- Smarter Match by Sawyer X

Feb 22, 2018 | www.perl.com

P5P update: Smarter Match

This post will be part of a new communication channel between p5p and the community. We hope to share more with you and keep you up-to-date using this platform.

On December 20th, 2017, we released Perl 5.27.7, which included a massive change to smartmatch . Since then it has been reverted. What happened?

Smartmatch has a long history. It was introduced in 5.10 back in December 2007 and significantly revised in 5.10.1. It was a good idea, but ended up causing more harm than good to the point it was deemed unreliable.

In an unprecedented step, it was marked as "experimental" in Perl 5.18.0, released in May 2013. Here is the mention of this in perldelta :

Smartmatch, added in v5.10.0 and significantly revised in v5.10.1, has been a regular point of complaint. Although there are some ways in which it is useful, it has also proven problematic and confusing for both users and implementors of Perl. There have been some proposals on how to best address the problem. It is clear that smartmatch is almost certainly either going to change or go away in the future. Relying on its current behavior is not recommended.

Warnings will now be issued when the parser sees ~~ , given , or when .

Since then, various threads were raised on how to resolve it. The decided approach was to simplify the syntax considerably. It took several rounds of discussions (with some bike-shedding) to settle what to simplify and to reach an agreement on the new behavior.

Last year we had finally reached an agreement on the significant perspectives. The changes were implemented by Zefram, a core developer. The work was published on a public branch for comments.

When no objections were filed, Zefram merged the new branch. It was included in the 5.27.7 development release.

Following the release of this development version, issues started popping up with the effect this change made. A fair portion of CPAN was breaking to the point that one of the dedicated Perl testers decided it was unfeasible for them to continue testing. Subsequently, we decided to revert this change.

What went wrong?

First of all, it was clear that moving smartmatch to experimental did not achieve what we had hoped. Features are marked as experimental to allow us to freely (for some value of "freely") adjust and tinker with them until we are comfortable making them stable. The policy is that any experimental feature can be declared stable after two releases with no behavioral change. With smartmatch, it was marked after numerous versions in which it existed as a stable feature.

Secondly, the change was massive. This in and of itself is not necessarily wrong, but how we handled it leaves room for improvement.

Thirdly, centering the communication around this change on the core mailing list was insufficient to receive enough feedback and eyes on the problem and the proposed solution. We should have published it off the list and sought more input and comments. We hope to use this platform to accomplish that.

Fourthly, we could have asked our dedicated testers for help on running additional, specific tests, to view what would break on CPAN and how damaging this change could be.

Where do we go from here?

Despite not being the best way to learn from a mistake, there was minimal damage. The new syntax and behavior were only available on a single development release, did not reach any production code, and was reverted within that single release.

To address smartmatch again, we will need to reflect upon our mistakes and consider approaching it again by communicating the change better and by receiving additional feedback to both offer a useful feature and pleasing syntax. This will take time, and we are not rushing to revisit smartmatch at the moment.

We apologize for the scare and we appreciate the quick responses to resolve this situation. Thank you.

[Sep 30, 2020] How to process command line arguments in Perl using Getopt--Long by Gabor Szabo

Oct 30, 2014 | perlmaven.com

When a Perl script is executed the user can pass arguments on the command line in various ways. For example perl program.pl file1.txt file2.txt or perl program.pl from-address to-address file1.txt file2.txt or, the most common and most useful way:

perl program.pl -vd --from from-address --to to-address file1.txt file2.txt

How can we deal with this information?

When the scripts starts to run, Perl will automatically create an array called @ARGV and put all the values on the command line separated by spaces in that variable. It won't include perl and it won't include the name of our script ( program.pl in our case), that will be placed in the $0 variable. @ARGV will only include the values located after the name of the script.

In the above case @ARGV will contain: ('-vd', '--from', 'from-address', '--to', 'to-address', 'file1.txt', 'file2.txt')

We can access @ARGV manually as described in the article about @ARGV , but there are a number of modules that will handle most of the work for you. In this article we'll see Getopt::Long a module that also comes with the standard installation of Perl.

Explain the command line

Just before doing that, let's see what is really our expectation from the command line processing.

There can be lots of other requirements and Getopt::Long can handle quite a few of them, but we'll focus on the basics.

Getopt::Long

Getopt::Long exports a function called GetOptions , that can process the content of @ARGV based on the configuration we give to it. It returns true or false indicating if the processing was successful or not. During processing it removes the items from @ARGV that have been successfully recognized. We'll take a look at possible errors later on. For now, let' see a small example we save in cli.pl :

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. use Getopt :: Long qw ( GetOptions );
  5. my $source_address ;
  6. GetOptions ( 'from=s' => \$source_address ) or die "Usage: $0 --from NAME\n" ;
  7. if ( $source_address ) {
  8. say $source_address ;
  9. }

After loading the module we declare a variable called $source_address where the value of the --from command line flag will be stored. We call GetOptions with key-value pairs. The keys (in this case one key) is the description of the flag. In this case the from=s declares that we are expecting a command line parameter called --from with a string after it. Because in Perl numbers can also be seen as strings, this basically means "pass me any value". This declaration is then mapped to the variable we declared earlier. In case the syntax is unclear => is a "fat arrow" you might be familiar from hashes and the back-slash \ in-front of the variable indicates that we are passing a reference to the variable. You don't need to understand references in order understand this code. Just remember that the variables on the right hand side of the "fat comma" operators need to have a back-slash when calling GetOptions .

We can run this program in several ways: perl cli.pl --from Foo will print "Foo". The value passed after the -from flag is assigned to the $source_address variable. On the other hand running perl cli.pl will not print anything as we have no passed any value.

If we run it perl cli.pl Foo it won't print anything either, as GetOptions only deals with options that start with a dash ( - ). (This is actually configurable, but let's not get there now.)

Failures

So when will the short circuit or die kick-in?

Unknown option

If we run the script passing something that looks like a parameter name, but which has not been declared when calling GetOptions . Something that starts with a dash - . For example:

perl cli.pl --to Bar

Unknown option: to
Usage: cli.pl --from NAME

The first line is a warning printed by GetOptions , the second line is the string we generated using die .

Option requires an argument

Another case is when we run the script, pass --from , but without passing any value after it:

perl cli.pl --from

In that case the output will look like this:

Option from requires an argument
Usage: cli.pl --from NAME

Here too, the first line was from GetOptions and the second line from our call to die . When we called GetOptions we explicitly said =s that we are expecting a string after the --from .

Default values

Often we would like to give a default value to one of the options. For example in the case of the --from field we might want it to default to the word 'Maven'. We can do it by assigning this value to the $source_address variable before calling GetOptions . For example, at the time we declare it using my .

  1. my $source_address = 'Maven' ;
  2. GetOptions ( 'from=s' => \$source_address ) or die "Usage: $0 --from NAME\n" ;
  3. if ( $source_address ) {
  4. say $source_address ;
  5. }

If the user does not pass the --from flag then GetOptions will not modify the value in the $source_address variable. Running perl cli.pl will result in "Maven".

Flags without value

In addition to parameters that require a value, we also would like to allow flags. Names, that by their presence make a difference. These things are used when we want to allow the users to turn on debugging, or to set the verbosity of the script.

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. use Getopt :: Long qw ( GetOptions );
  5. my $debug ;
  6. GetOptions ( 'debug' => \$debug ) or die "Usage: $0 --debug\n" ;
  7. say $debug ? 'debug' : 'no debug' ;

Originally the $debug variable contained undef which is considered to be false in Perl. If the user passes the --debug flag, the corresponding variable will be set to some true value. (I think it is the number one, but we should only rely on the fact that it evaluates to true.) We then use the ternary operator to decide what to print.

The various ways we call it and the output they produce:

$ perl cli.pl 
no debug

$ perl cli.pl --debug
debug

$ perl cli.pl --debug hello
debug

The last example shows that values placed after such name are disregarded.

Multiple flags

Obviously, in most of the scripts you will need to handle more than one flag. In those cases we still call GetOptions once and provide it with all the parameters:

Combining the above two cases together we can have a larger example:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. use Getopt :: Long qw ( GetOptions );
  5. my $debug ;
  6. my $source_address = 'Maven' ;
  7. GetOptions (
  8. 'from=s' => \$source_address ,
  9. 'debug' => \$debug ,
  10. ) or die "Usage: $0 --debug --from NAME\n" ;
  11. say $debug ? 'debug' : 'no debug' ;
  12. if ( $source_address ) {
  13. say $source_address ;
  14. }

Running without any parameter will leave $debug as undef and the $source_address as 'Maven':

$ perl cli.pl 
no debug
Maven

Passing --debug will set $debug to true, but will leave $source_address as 'Maven':

$ perl cli.pl --debug
debug
Maven

Passing --from Foo will set the $source_address but leave $debug as undef :

$ perl cli.pl  --from Foo
no debug
Foo

If we provide parameters, they will both set the respective variables:

$ perl cli.pl --debug --from Foo
debug
Foo

The order of the parameters on the command line does not matter:

$ perl cli.pl  --from Foo --debug
debug
Foo
Short names

Getopt::Long automatically handles shortening of the option names up to ambiguity. We can run the above script in the following manner:

$ perl cli.pl --fr Foo --deb
debug
Foo

We can even shorten the names to a single character:

$ perl cli.pl --f Foo --d
debug
Foo

and in that case we can even use single-dash - prefixes:

$ perl files/cli.pl -f Foo -d
debug
Foo

These however are not really single-character options, and as they are they cannot be combined:

$ perl cli.pl -df Foo
Unknown option: df
Usage: cli.pl --debug  --from NAME
Single-character options

In order to combine them we need two do two things. First, we need to declare the options as real single-character options. We can do this by providing alternate, single-character names in the definition of the options:

  1. GetOptions (
  2. 'from|f=s' => \$source_address ,
  3. 'debug|d' => \$debug ,
  4. ) or die "Usage: $0 --debug --from NAME\n" ;

The second thing is that we need to enable the gnu_getopt configuration option of Getopt::Long by calling Getopt::Long::Configure qw(gnu_getopt);

  1. use Getopt :: Long qw ( GetOptions );
  2. Getopt :: Long :: Configure qw ( gnu_getopt );

After doing that we can now run

$ perl cli.pl -df Foo
debug
Foo

The full version of the script with the above changes looks like this:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. use Getopt :: Long qw ( GetOptions );
  5. Getopt :: Long :: Configure qw ( gnu_getopt );
  6. use Data :: Dumper ;
  7. my $debug ;
  8. my $source_address = 'Maven' ;
  9. GetOptions (
  10. 'from|f=s' => \$source_address ,
  11. 'debug|d' => \$debug ,
  12. ) or die "Usage: $0 --debug --from NAME\n" ;
  13. say $debug ? 'debug' : 'no debug' ;
  14. if ( $source_address ) {
  15. say $source_address ;
  16. }
Non-affiliated values

The GetOptions function only handles the parameters that start with a dash and their corresponding values, when they are relevant. Once it processed the options it will remove them from @ARGV . (Both the option name and the option value will be removed.) Any other, non-affiliated values on the command line will stay in @ARGV . Hence if we add Data::Dumper to our script and use that to print the content of @ARGV at the end ( print Dumper \@ARGV ) as in this script:

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. use Getopt :: Long qw ( GetOptions );
  5. use Data :: Dumper ;
  6. my $debug ;
  7. my $source_address = 'Maven' ;
  8. GetOptions (
  9. 'from=s' => \$source_address ,
  10. 'debug' => \$debug ,
  11. ) or die "Usage: $0 --debug --from NAME\n" ;
  12. say $debug ? 'debug' : 'no debug' ;
  13. if ( $source_address ) {
  14. say $source_address ;
  15. }
  16. print Dumper \@ARGV ;

We get the following results:

$ perl files/cli.pl  -f Foo -d file1.txt file2.txt
debug
Foo
$VAR1 = [
          'file1.txt',
          'file2.txt'
        ];

After processing the options, file1.txt and file2.txt were left in @ARGV . We can now do whatever we want with them, for example we can iterate over the @ARGV array using foreach .

Advanced

Getopt::Long has tons of other options. You might want to check out the documentation.

There are also other solutions, for example if you are using Moo for light-weight object oriented programming, you could take a look at MooX::Options explained in a number of advanced articles: for example Switching to Moo - adding command line parameters and Writing Command line scripts and accepting command line parameters using Moo .

[Sep 30, 2020] Postfix if conditions are useful mainly to specify exist condition in the loop, rarely elsewhere

Sep 30, 2020 | perlmonks.org

Re^6: What esteemed monks think about changes necessary/desirable in Perl 7 outside of OO staff
by likbez on Sep 27, 2020 at 22:37 UTC

We need not "assume that somebody uses this formatting". I do it frequently, and I have often seen it in other people's code. That fact that you use it and saw it in other people code means nothing. People often adopt and use bad programming style. Even talented programmers do. Look at classic The Elements of Programming Style , by Brian W. Kernighan and P. J. Plauger. They include such recommendations as ( cited from https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style ) :

The real question is whether the use you advocate represents a good Perl programming style or not.

I would understand the use of post-fix if construct in a loop to specify exit condition. Something like:

return if ($exit_condition);
They make code more readable in comparison with the regular if statement as as such have certain value and IMHO represent a good programming style.

In many other cases the desire to save two curly braces looks to me a very questionable practice and a bad programming style. Your mileage may vary.

[Sep 29, 2020] At what point excessive syntactic flexibility stimulates perverted programming style which is reflected in the derogative term "complexity junkies"?

Notable quotes:
"... In your private role you are free to do whatever you wish. After all programming open source is about fun, not so much about discipline. ..."
"... The situation radically changes in commercial projects. If you are a manager of a large project you need to ensure a uniform and preferably simple style via guidelines that explicitly prohibit such "excesses" and to step on the throat of such "excessively creative" people to make them "behave". ..."
"... That's why languages that allow too much syntactic freedom are generally not welcomed in large commercial projects, even if they are able to manage large namespaces more or less OK. ..."
Sep 29, 2020 | perlmonks.org

likbez on Sep 29, 2020 at 18:01 UTC

Re^11: What esteemed monks think about changes necessary/desirable in Perl 7 outside of OO staff

by likbez on Sep 29, 2020 at 18:01 UTC

If I have to maintain (as only maintainer) a piece of perl code, I will *rewrite* *all* statements as you state from action if expression; to expression and action; as that (to me) is waaaaaaaaaay easier to read/understand/maintain. Nothing to do with "idiomatic perl". Nothing at all!
People are extremely flexible. The same is true for programmers. Many of talented programmers I encountered have a somewhat idiosyncratic style...

In your private role you are free to do whatever you wish. After all programming open source is about fun, not so much about discipline.

The situation radically changes in commercial projects. If you are a manager of a large project you need to ensure a uniform and preferably simple style via guidelines that explicitly prohibit such "excesses" and to step on the throat of such "excessively creative" people to make them "behave".

That's why languages that allow too much syntactic freedom are generally not welcomed in large commercial projects, even if they are able to manage large namespaces more or less OK.

Let's be frank: Perl lost Web applications development more or less completely. The reasons are not clear and can be argued, but the fact is indisputable. But the problem that I see is that Perl can lose attraction among sysadmins because of excessive push of OO programming style by OO-fanatics and the second rate book authors, as well as due to inability of distribute remaining scarce development resources toward modest and not fancy (unlike closures, accessors, frameworks and other fancy staff) improvements in the procedural programming arena (the area which this post is all about).

An interesting question is: at what point excessive syntactic flexibility stimulates perverted programming style which is reflected in the derogative term "complexity junkies"? When in the program simple things look complex, and complex unmanageable. "Object oriented spaghetti" ('Lasagna code' with too many layers) is another term that addresses the same problem. See, for example, discussion at https://medium.com/better-programming/is-object-oriented-programming-garbage-66c4f41adcaa

Also https://www.youtube.com/watch?time_continue=9&v=V6VP-2aIcSc&feature=emb_logo

[Sep 16, 2020] Wantarray

Sep 16, 2020 | perlmonks.org

Returns true if the context of the currently executing subroutine or eval is looking for a list value. Returns false if the context is looking for a scalar. Returns the undefined value if the context is looking for no value (void context).

Re^8: What esteemed monks think about changes necessary/desirable in Perl 7 outside of OO staff
by Fletch on Sep 15, 2020 at 15:51 UTC

Had a reeeeeaaaaly vague recollection and the Perl Cookbook (Ch 1 section 19) does actually offer $_ = join(' ', split(' ')); as an alternative to these three substitutions:

s/^\s+//; s/\s+$//; s/\s+/ /g; [download]

to strip and canonicalize to single spaces; and does offer this trim sub:

sub trim { my @out = @_ ? @_ : $_; $_ = join(' ', split(' ')) for @out; return wantarray ? @out : "@out"; } [download]

Edit: That being said, I don't recall having seen this construct in the wild otherwise and had the vaguest of hunches that PC mentioned anything like this so I'd hardly call it a "common idiom" either.

[Sep 14, 2020] Promoting Perl and Perl-based Projects- - perl

Sep 14, 2020 | www.reddit.com


Three things occur to me that could help Perl.

At least in the US all other things being equal there is a tendency to root for the underdog in any given conflict. Python is seen as king. Perl is seen as an "old man's language." Never mind the two languages are contemporaries and Perl that follows best practices isn't difficult to follow.

My first thought its we can probably leverage the psychological tendency to root for the underdog as means to promote the language. Let's talk about that. Am I right? Am I wrong?

Second, it seems that there are very few Code Academy type sites that support and promote Perl as a language worth learning. I keep hearing about the need for "fresh blood." Well, I'm "fresh blood" but I used books from Amazon to get where I'm at. I'm still in the process of learning. It seems most younger developers just want to go from one structured tutorial to another without buying a print or even Kindle book.

So, how do we promote Perl to such sites? That's a major bottle neck, I think. Sure, Python dominates but there is space for Rust and Go devops. I see space for Perl at the table too.

Third, there are lots of small to medium sized projects that happen to be written in Perl that don't get a lot of visibility. Sure, they're (probably) on CPAN, but we can't all know everything.

Someone made a point to me in another post that programming languages are like gods in some fantasy literature: they lose power as others stop believing in them. Point taken. So, let's increase the number of devotees by talking about these projects and their usefulness.

What are some cool projects out there that leverage the best of Perl that don't get the visibility they deserve? Yes, you can plug your own project and/or talk about its challenges.


level 1

vvelox 8 points· 3 days ago

· edited 3 days ago
level 1 relishketchup 5 points· 3 days ago
· edited 3 days ago

Paws is another great example of modern tools which allows you to use Perlish code (instead of Boto3 in Python) for AWS

Rex is an Ansible-like automation tool written in Perl

vvelox 4 points· 3 days ago

Rex is an Ansible-like automation tool written in Perl

I love rex. So much more friendly than ansible and so bloody flexible. erkiferenc 3 points· 2 days ago

Rex is cool, but no one is adopting it over Ansible/Salt/Puppet/etc.

As Rex maintainer, I feel the words "no one" to be too strong in this context, so let me clarify that claim a bit :)

I agree that the market share is relatively low. Partly because it's a volunteers-only project, and I'm currently not aware of anybody actively flooding the advertisement channels with Rex content in their free time (and for free). Anybody willing to change that, please go ahead!

Another factor for relatively low visibility is that the purpose of Rex, as a framework, is to allow one to build their own automation tool required to solve their own needs. This means most of the Rex-based solutions are custom-made. So it's often too specific for their own situation, or they don't have the permissions to publish it.

Personally, I have more first-hand experience with use cases where Rex is used right form the start. Based on community reports, it's also fairly common that one of the alternatives are replaced with Rex at some point. Overall there are known use cases ranging from one-man shows to tens of thousands of servers.

I guess we gotta put up a success stories page or similar to the website to give those cases more visibility :) Until then, please feel free to blog about it, tweet about it, give a talk at the next event, star it on GitHub, favorite it on MetaCPAN, vote on StackShare...or even hire/sponsor me to do it all! :D
level 1 DerBronco 9 points· 3 days ago

I am living in a 25k town with no metropolitan area within 200km.

My client is a leading importer and big wholesaler with a big shipping warehouse.

Our backoffice runs in perl. The warehouse in/out is perl/mariadb.

There are dozens of retailers and dropshippers connected to our db, some pushing, some csv/xml-generators, OpenTrans, shopify, even Lexware-odbc based stuff.

All of it individual code in perl. And not even hip modern perl, but rather oldschool stuff, only few cpan modules etc

that makes me indespensable. There are simply no perl coders in the wider area. It wouldnt even make sense to train somebody in perl AND my codebase thats been growing since 2003 because that will take years.

And thats why im staying with perl.

TLDR: using underdog coding language will make my living and pay my bills till retirement.

Lets it be the underdog please ;) hurricup 1 point· 2 days ago

Perl now have a full featured IDE with IntelliJ IDEA and perl plugin: https://github.com/Camelcade/Perl5-IDEA
level 1 szabgab 0 points· 19 hours ago

· edited 19 hours ago

If I may, I'd like to challenge you asking why would you like to promote Perl and Perl-based projects?

I think in order for this to be successful you need to formulate an answer to that question.

I know why would it be great for me, but:

What do you gain from Perl being more popular? What do others gain from it? Who has interest in it? Who has the energy and time to invest in this effort? Who might have money to financially support Perl-related promotional or development efforts?

[Sep 11, 2020] Why are Perl 5's function prototypes bad

Jan 01, 2008 | stackoverflow.com

Ask Question Asked 11 years, 10 months ago Active 4 years, 4 months ago Viewed 19k times

https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html Report this ad


Alnitak , 2008-11-17 21:37:57

116 32

In another Stack Overflow question Leon Timmermans asserted:

I would advice you not to use prototypes. They have their uses, but not for most cases and definitely not in this one.

Why might this be true (or otherwise)? I almost always supply prototypes for my Perl functions, and I've never before seen anyone else say anything bad about using them. perl function prototype share improve this question follow edited May 23 '17 at 11:54 Community ♦ 1 1 1 silver badge asked Nov 17 '08 at 21:37 Alnitak 303k 67 67 gold badges 368 368 silver badges 458 458 bronze badges

tchrist ,

I'm curious too. The only time I don't use them is when I'm calling with a variable number of arguments. – Paul Tomblin Nov 17 '08 at 21:56

Michael Carman , 2008-11-17 22:54:09

121

Prototypes aren't bad if used correctly. The difficulty is that Perl's prototypes don't work the way people often expect them to. People with a background in other programming languages tend to expect prototypes to provide a mechanism for checking that function calls are correct: that is, that they have the right number and type of arguments. Perl's prototypes are not well-suited for this task. It's the misuse that's bad. Perl's prototypes have a singular and very different purpose:

Prototypes allow you to define functions that behave like built-in functions.

For example, you could define a function like this:

sub mypush(\@@) { ... }

and call it as

mypush @array, 1, 2, 3;

without needing to write the \ to take a reference to the array.

In a nutshell, prototypes let you create your own syntactic sugar. For example the Moose framework uses them to emulate a more typical OO syntax.

This is very useful but prototypes are very limited:

See Prototypes in perlsub for all the gory details. share improve this answer follow edited Feb 25 '16 at 16:37 ikegami 306k 14 14 gold badges 212 212 silver badges 448 448 bronze badges answered Nov 17 '08 at 22:54 Michael Carman 29.7k 9 9 gold badges 69 69 silver badges 119 119 bronze badges

Peter Mortensen ,

I've accepted this answer because I feel it best answers the question - prototypes aren't intrinsically bad, it's just how you use them. – Alnitak Nov 18 '08 at 19:53

cjm , 2008-11-17 21:55:27

69

The problem is that Perl's function prototypes don't do what people think they do. Their purpose is to allow you to write functions that will be parsed like Perl's built-in functions.

First of all, method calls completely ignore prototypes. If you're doing OO programming, it doesn't matter what prototype your methods have. (So they shouldn't have any prototype.)

Second, prototypes aren't strictly enforced. If you call a subroutine with &function(...) , the prototype is ignored. So they don't really provide any type safety.

Third, they're spooky action-at-a-distance. (Especially the $ prototype, which causes the corresponding parameter to be evaluated in scalar context, instead of the default list context.)

In particular, they make it hard to pass parameters from arrays. For example:

my @array = qw(a b c);

foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);

sub foo ($;$$) { print "@_\n" }

foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);

prints:

a b c
a b
a b c
3
b
a b c

along with 3 warnings about main::foo() called too early to check prototype (if warnings are enabled). The problem is that an array (or array slice) evaluated in scalar context returns the length of the array.

If you need to write a function that acts like a built-in, use a prototype. Otherwise, don't use prototypes.

Note: Perl 6 will have completely revamped and very useful prototypes. This answer applies only to Perl 5. share improve this answer follow edited Nov 20 '14 at 15:11 Flimm 85.8k 28 28 gold badges 185 185 silver badges 189 189 bronze badges answered Nov 17 '08 at 21:55 cjm 58.8k 8 8 gold badges 117 117 silver badges 164 164 bronze badges

Flimm ,

But they still provide a useful check that your caller and the sub are using the same number of arguments, so what's wrong with that? – Paul Tomblin Nov 17 '08 at 21:57

Leon Timmermans ,

30

I agree with the above two posters. In general, using $ should be avoided. Prototypes are only useful when using block arguments ( & ), globs ( * ), or reference prototypes ( \@ , \$ , \% , \* ) share improve this answer follow answered Nov 18 '08 at 17:26 Leon Timmermans 28.9k 2 2 gold badges 57 57 silver badges 109 109 bronze badges

The Sidhekin ,

In general, perhaps, but I'd like to mention two exceptions: First, the ($) prototype creates a named unary operator, which can be useful (certainly Perl finds them useful; I have too, on occasion). Second, when overriding built-ins (whether through import or using CORE::GLOBAL::), you should in general stick to whatever prototype the built-in had, even if that includes a $ , or you might surprise the programmer (yourself, even) with list context where the built-in would otherwise provide scalar context. – The Sidhekin Sep 9 '15 at 21:47

> ,

4

Some people, looking at a Perl subroutine prototype, thinks it means something that it doesn't:

sub some_sub ($$) { ... }

To Perl, that means that the parser expects two arguments. It's Perl's way of letting you create subroutines that behave like built-ins, all of which know what to expect from the succeeding code. You can read about prototypes in perlsub

Without reading the documentation, people guess that the prototypes refer to run time argument checking or something similar that they've seen in other languages. As with most things people guess about Perl, they turn out to be wrong.

However, starting with Perl v5.20, Perl has a feature, experimental as I write this, that gives something more like what users expect and what. Perl's subroutine signatures does run time argument counting, variable assigning, and default setting:

use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);

animals( 'Buster', 'Nikki', 'Godzilla' );

sub animals ($cat, $dog, $lizard = 'Default reptile') { 
    say "The cat is $cat";
    say "The dog is $dog";
    say "The lizard is $lizard";
    }

This is the feature you probably want if you're considering prototypes.

[Sep 11, 2020] Prototypes (Programming Perl)

Sep 11, 2020 | docstore.mik.ua

6.4. Prototypes

Perl lets you define your own functions to be called like Perl's built-in functions. Consider push(@array, $item) , which must tacitly receive a reference to @array , not just the list values held in @array , so that the array can be modified. Prototypes let you declare subroutines to take arguments just like many of the built-ins, that is, with certain constraints on the number and types of arguments. We call them "prototypes", but they work more like automatic templates for the calling context than like what C or Java programmers would think of as prototypes. With these templates, Perl will automatically add implicit backslashes, or calls to scalar , or whatever else it takes to get things to show up in a way that matches the template. For instance, if you declare:

sub mypush (\@@);
then mypush takes arguments exactly like push does. For this to work, the declaration of the function to be called must be visible at compile time. The prototype only affects the interpretation of function calls when the & character is omitted. In other words, if you call it like a built-in function, it behaves like a built-in function. If you call it like an old-fashioned subroutine, then it behaves like an old-fashioned subroutine. The & suppresses prototype checks and associated contextual effects.

Since prototypes are taken into consideration only at compile time, it naturally falls out that they have no influence on subroutine references like \&foo or on indirect subroutine calls like &{$subref} or $subref->() . Method calls are not influenced by prototypes, either. That's because the actual function to be called is indeterminate at compile time, depending as it does on inheritance, which is dynamically determined in Perl.

Since the intent is primarily to let you define subroutines that work like built-in functions, here are some prototypes you might use to emulate the corresponding built-ins:

Declared as Called as
sub mylink ($$) mylink $old, $new
sub myreverse (@) myreverse $a,$b,$c
sub myjoin ($@) myjoin ":",$a,$b,$c
sub mypop (\@) mypop @array
sub mysplice (\@$$@) mysplice @array,@array,0,@pushme
sub mykeys (\%) mykeys %{$hashref}
sub mypipe (**) mypipe READHANDLE, WRITEHANDLE
sub myindex ($$;$) myindex &getstring, "substr"
myindex &getstring, "substr", $start
sub mysyswrite (*$;$$) mysyswrite OUTF, $buf
mysyswrite OUTF, $buf, length($buf)-$off, $off
sub myopen (*;$@) myopen HANDLE
myopen HANDLE, $name
myopen HANDLE, "-|", @cmd
sub mygrep (&@) mygrep { /foo/ } $a,$b,$c
sub myrand ($) myrand 42
sub mytime () mytime

Any backslashed prototype character (shown between parentheses in the left column above) represents an actual argument (exemplified in the right column), which absolutely must start with that character. Just as the first argument to keys must start with % , so too must the first argument to mykeys .

A semicolon separates mandatory arguments from optional arguments. (It would be redundant before @ or % , since lists can be null.) Unbackslashed prototype characters have special meanings. Any unbackslashed @ or % eats all the rest of the actual arguments and forces list context. (It's equivalent to LIST in a syntax description.) An argument represented by $ has scalar context forced on it. An & requires a reference to a named or anonymous subroutine.

A * allows the subroutine to accept anything in that slot that would be accepted by a built-in as a filehandle: a bare name, a constant, a scalar expression, a typeglob, or a reference to a typeglob. The value will be available to the subroutine either as a simple scalar or (in the latter two cases) as a reference to the typeglob. If you wish to always convert such arguments to a typeglob reference, use Symbol::qualify_to_ref as follows:

use Symbol 'qualify_to_ref';

sub foo (*) {
    my $fh = qualify_to_ref(shift, caller);
    ...
}
Note how the last three examples in the table are treated specially by the parser. mygrep is parsed as a true list operator, myrand is parsed as a true unary operator with unary precedence the same as rand , and mytime is truly argumentless, just like time .

That is, if you say:

mytime +2;
you'll get mytime() + 2 , not mytime(2) , which is how it would be parsed without the prototype, or with a unary prototype.

The mygrep example also illustrates how & is treated specially when it is the first argument. Ordinarily, an & prototype would demand an argument like \&foo or sub{} . When it is the first argument, however, you can leave off the sub of your anonymous subroutine, and just pass a bare block in the "indirect object" slot (with no comma after it). So one nifty thing about the & prototype is that you can generate new syntax with it, provided the & is in the initial position:

sub try (&$) {
    my ($try, $catch) = @_;
    eval { &$try };
    if ($@) {
        local $_ = $@;
        &$catch;
    }
}
sub catch (&) { $_[0] }

try {
    die "phooey";
}                   # not the end of the function call!
catch {
    /phooey/ and print "unphooey\n";
};
This prints " unphooey ". What happens is that try is called with two arguments, the anonymous function {die "phooey";} and the return value of the catch function, which in this case is nothing but its own argument, the entire block of yet another anonymous function. Within try , the first function argument is called while protected within an eval block to trap anything that blows up. If something does blow up, the second function is called with a local version of the global $_ variable set to the raised exception. [3] If this all sounds like pure gobbledygook, you'll have to read about die and eval in Chapter 29, "Functions" , and then go check out anonymous functions and closures in Chapter 8, "References" . On the other hand, if it intrigues you, you might check out the Error module on CPAN, which uses this to implement elaborately structured exception handling with try , catch , except , otherwise , and finally clauses.

[3] Yes, there are still unresolved issues having to do with the visibility of @_ . We're ignoring that question for the moment. But if we make @_ lexically scoped someday, as already occurs in the experimental threaded versions of Perl, those anonymous subroutines can act like closures.

Here's a reimplementation of the grep operator (the built-in one is more efficient, of course):

sub mygrep (&@) {
    my $coderef = shift;
    my @result;
    foreach $_ (@_) {
        push(@result, $_) if &$coderef;
    }
    return @result;
}
Some folks would prefer to see full alphanumeric prototypes. Alphanumerics have been intentionally left out of prototypes for the express purpose of someday adding named, formal parameters. (Maybe.) The current mechanism's main goal is to let module writers enforce a certain amount of compile-time checking on module users. 6.4.1. Inlining Constant Functions

Functions prototyped with () , meaning that they take no arguments at all, are parsed like the time built-in. More interestingly, the compiler treats such functions as potential candidates for inlining. If the result of that function, after Perl's optimization and constant-folding pass, is either a constant or a lexically scoped scalar with no other references, then that value will be used in place of calls to that function. Calls made using & NAME are never inlined, however, just as they are not subject to any other prototype effects. (See the use constant pragma in Chapter 31, "Pragmatic Modules" , for an easy way to declare such constants.)

Both version of these functions to compute will be inlined by the compiler:

sub pi ()           { 3.14159 }             # Not exact, but close
sub PI ()           { 4 * atan2(1, 1) }     # As good as it gets
In fact, all of the following functions are inlined because Perl can determine everything at compile time:
sub FLAG_FOO ()     { 1 << 8 }
sub FLAG_BAR ()     { 1 << 9 }
sub FLAG_MASK ()    { FLAG_FOO | FLAG_BAR }

sub OPT_GLARCH ()   { (0x1B58 & FLAG_MASK) == 0 }
sub GLARCH_VAL ()   {
    if (OPT_GLARCH) { return 23 }
    else            { return 42 }
}

sub N () { int(GLARCH_VAL) / 3 }
BEGIN {                 # compiler runs this block at compile time
    my $prod = 1;       # persistent, private variable
    for (1 .. N) { $prod *= $_ }
    sub NFACT () { $prod }
}
In the last example, the NFACT function is inlined because it has a void prototype and the variable it returns is not changed by that function--and furthermore can't be changed by anyone else, since it's in a lexical scope. So the compiler replaces uses of NFACT with that value, which was precomputed at compile time because of the surrounding BEGIN .

If you redefine a subroutine that was eligible for inlining, you'll get a mandatory warning. (You can use this warning to tell whether the compiler inlined a particular subroutine.) The warning is considered severe enough not to be optional, because previously compiled invocations of the function will still use the old value of the function. If you need to redefine the subroutine, ensure that it isn't inlined either by dropping the () prototype (which changes calling semantics, so beware) or by thwarting the inlining mechanism in some other way, such as:

sub not_inlined () {
    return 23 if $$;
}
See Chapter 18, "Compiling" for more about what happens during the compilation and execution phases of your program's life. 6.4.2. Care with Prototypes

It's probably best to put prototypes on new functions, not retrofit prototypes onto older ones. These are context templates, not ANSI C prototypes, so you must be especially careful about silently imposing a different context. Suppose, for example, you decide that a function should take just one parameter, like this:

sub func ($) {
    my $n = shift;
    print "you gave me $n\n";
}
That makes it a unary operator (like the rand built-in) and changes how the compiler determines the function's arguments. With the new prototype, the function consumes just one, scalar-context argument instead of many arguments in list context. If someone has been calling it with an array or list expression, even if that array or list contained just a single element, where before it worked, now you've got something completely different:
func @foo;                  # counts @foo elements
func split /:/;             # counts number of fields returned
func "a", "b", "c";         # passes "a" only, discards "b" and "c"
func("a", "b", "c");        # suddenly, a compiler error!
You've just supplied an implicit scalar in front of the argument list, which can be more than a bit surprising. The old @foo that used to hold one thing doesn't get passed in. Instead, 1 (the number of elements in @foo ) is now passed to func . And the split , being called in scalar context, scribbles all over your @_ parameter list. In the third example, because func has been prototyped as a unary operator, only " a " is passed in; then the return value from func is discarded as the comma operator goes on to evaluate the next two items and return " c ." In the final example, the user now gets a syntax error at compile time on code that used to compile and run just fine.

If you're writing new code and would like a unary operator that takes only a scalar variable, not any old scalar expression, you could prototype it to take a scalar reference :

sub func (\$) {
    my $nref = shift;
    print "you gave me $$nref\n";
}
Now the compiler won't let anything by that doesn't start with a dollar sign:
func @foo;              # compiler error, saw @, want $
func split/:/;          # compiler error, saw function, want $
func $s;                # this one is ok -- got real $ symbol
func $a[3];             # and this one
func $h{stuff}[-1];     # or even this
func 2+5;               # scalar expr still a compiler error
func ${ \(2+5) };       # ok, but is the cure worse than the disease?
If you aren't careful, you can get yourself into trouble with prototypes. But if you are careful, you can do a lot of neat things with them. This is all very powerful, of course, and should only be used in moderation to make the world a better place.

[Sep 10, 2020] Use v5.20 subroutine signatures

Sep 10, 2020 | www.effectiveperlprogramming.com

Use v5.20 subroutine signatures Posted by brian d foy on April 16, 2015 Leave a comment (14) Go to comments

Subroutine signatures, in a rudimentary form, have shown up in Perl v5.20 as an experimental feature. After a few of years of debate and a couple of competing implementations, we have something we can use. And, because it was such a contentious subject, it got the attention a new feature deserves. They don't have all the features we want (notably type and value constraints), but Perl is in a good position to add those later.

Perl's roots were in simplicity and getting started as quickly as possible. We wanted to define subroutines without much work. Instead of creating signatures in a C header file and worrying about inputs and outputs, Larry made subroutines take in lists and return lists. Done and done.

This simplicity means you have to do quite a bit of work yourself. You have to process the input list, in @_ , assign your own default values, and declare the variables to possibly store them. You ended up not saving much for the typical programmer.

To start, you need to enable the experimental feature (see Item 2. Enable new Perl features when you need them. and turn off the experimental warnings ):

1 use v5.20;
2 use feature qw(signatures);
3 no warnings qw(experimental::signatures);

To define a signature, you use the spot after the subroutine name where so far Perl has only allowed a prototype. This is not a prototype though; it's something different. Notably, the new subroutine signatures work with methods, whereas prototypes are compiler hints that method calls ignore:

01 use v5.10;
02
03 sub some_sub ($$) {
04 say "I got $_[0] and $_[1]" ;
05 }
06
07 some_sub( 'Buster' , 'Mimi' );
08
09 main->some_sub(); # "works" just fine
10
11 some_sub( qw(Buster) ); # compile time error

But, you have a limited set of characters you can put in a prototype, and those exclude identifier characters (those we use to make names). If you've enabled this experimental feature and Perl see un-prototype like characters, it tries signatures instead. Note that Perl has another feature like this: the diamond operator, <> , which might actually be the glob operator if Perl sees glob characters in the argument. You can still use a prototype with signatures, but you probably shouldn't use prototypes. The perlsub documentation shows you how you can use an attribute to make a prototype.

First, be aware that using a signature does not mess with the normal argument list in @_ . You can still play with that yourself.

The simplest prototype

The simplest signature is like the simplest prototype. Like prototypes, the signature enforces the number of arguments. To make a constant in Perl you can use a subroutine that takes no arguments. This is essentially what the constant pragma does:

1 use v5.20;
2 use feature qw(signatures);
3 no warnings qw(experimental::signatures);
4
5 sub cat () { 'Buster' }
6
7 say "Cat is " , cat;

If you try to pass an argument, you'll get an error but at runtime:

1 use v5.20;
2 use feature qw(signatures);
3 no warnings qw(experimental::signatures);
4
5 sub cat () { 'Buster' }
6 say "Running..." ;
7 say "Cat is " , cat( 'Mini' );

The first say works, but the second fails when it calls cat incorrectly:

1 Running...
2 Too many arguments for subroutine at cat.pl line 7.

A prototype would have raised a compile-time error because the compiler already knows how many arguments there should be. This doesn't mean that the experimental signatures might do that later, but the implementation now is more of a code mangler. Deparsing it ( Use B::Deparse to see what perl thinks the code is ) shows that the cat subroutine has a die triggered by a check of @_ :

01 $ perl5.20.0 -MO=Deparse cat.pl
02 sub BEGIN {
03 require v5.20;
04 }
05 sub cat {
06 BEGIN {${^WARNING_BITS} = "\020\001\000\000\000P\004\000\000\000\000\000\000U\005"}
07 use strict;
08 use feature 'current_sub', 'evalbytes', 'fc', 'say', 'signatures', 'state', 'switch', 'unicode_strings', 'unicode_eval';
09 no feature 'array_base';
10 die 'Too many arguments for subroutine' unless @_ <= 0;
11 ();
12 'Buster';
13 }
14 BEGIN {${^WARNING_BITS} = "\020\001\000\000\000P\004\000\000\000\000\000\000U\005"}
15 use strict;
16 use feature 'current_sub', 'evalbytes', 'fc', 'say', 'signatures', 'state', 'switch', 'unicode_strings', 'unicode_eval';
17 no feature 'array_base';
18 say 'Cat is ', cat('Mini');
19 test.pl syntax OK

Don't get too hung up on that because it might be a temporary implementation detail. This does mean, however, that you can catch this error with eval :

1 use v5.20;
2 use feature qw(signatures);
3 no warnings qw(experimental::signatures);
4
5 sub cat () { 'Buster' }
6 say "Running...";
7 say "Cat is ", eval { cat( 'Mini') };
8
9 say "Caught error: $@" if $@;

Now we catch the error, but notice it comes from the line of the subroutine definition, not the point where you called the subroutine like you would with a croak :

1 Running...
2 Cat is
3 Caught error: Too many arguments for subroutine at cat.pl line 5.
Mandatory, positional parameters

The meat of this feature is your ability to assign to variables in what many perceive as a prettier way. Instead of declaring variables, usually with my , and performing list operations on @_ , you list the variables in the signature in the order you would assign from @_ :

1 use v5.20;
2 use feature qw(signatures);
3 no warnings qw(experimental::signatures);
4
5 cat( 'Buster' );
6
7 sub cat ($cat) {
8 say "The cat is $cat";
9 }

Again, this checks the number of parameters. With no arguments or more than one argument you get a runtime error.

You separate multiple arguments with commas, just like a list assignment:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 animals( 'Buster', 'Nikki', 'Godzilla' );
06
07 sub animals ($cat, $dog, $lizard) {
08 say "The cat is $cat";
09 say "The dog is $dog";
10 say "The lizard is $lizard";
11 }

These variables are lexical variables in the scope of the subroutine (as you'd see if you deparsed this code). That means you can't assign to special variables, which would cause an compile-time error. That is, except for $_ , which is experimentally lexical from a v5.10 misadventure with given-when ( Perl v5.16 now sets proper magic on lexical $_ and Use for() instead of given() ).

Placeholder parameters

You don't have to name all of the parameters. You can use the lone $ to not immediately assign a value, probably because you'll process it yourself through @_ . In this example we don't care about the second argument, but the signature still needs the right number of positions and in the right sequence:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 animals( 'Buster', 'Nikki', 'Godzilla' );
06
07 sub animals ($cat, $, $lizard) { # unnamed second parameter
08 say "The cat is $cat";
09 say "The lizard is $lizard";
10 }

This is a bit tricky really. That second argument is mandatory even though you've neglected to give it a name. It will still be in @_ even though you haven't assigned it to a variable.

Slurpy parameters

At the end of the parameter list, you can have a slurpy parameter, which is either a named array or hash. You can do this is a list assignment too, but a list assignment lets you put it in the middle despite the fact that any succeeding elements get nothing:

1 my ( $cat , $dog , @animals , $lizard ) # $lizard will never get anything
2 = qw( Buster Nikki Ginger Mimi Godzilla );

In the subroutine signature, that slurpy thing has to be at the end of the list:

1 sub animals ( $cat , $dog , @animals ) { # @animals must be at the end
2 ...;
3 }

The rest of the arguments past the second show up in @animals . But, here's the interesting thing; the number of things that can show up in the array can be zero.

Sometimes you may not want to completely specify the number of arguments that your subroutine may take, but you also don't want to create a named array, you can use a bare @ as placeholder to mean that the argument list is unlimited:

1 sub animals ( $cat , $dog , @ ) { # @ slurps the rest
2 ...;
3 }

The hash can also be a slurpy parameter, and just like the slurpy array it must be at the end of the signature:

1 sub animals ( $cat , $dog , %args ) { # %args demands an even number
2 ...;
3 }

For the hash, if there isn't an even number of elements left in @_ , you'll get a runtime exception. You don't have to name the hash, and a bare % still demands an even number of elements:

1 sub animals ( $cat , $dog , % ) { # % still demands an even number
2 ...;
3 }
Default values (optional parameters)

Perhaps the best feature of signatures are default values. You can use Perl to decide what the default values, even if that is a literal. However, you can only assign default values to optional parameters, which means that they have to appear after the mandatory arguments. In this example, the third argument is optional and gets the default value 'MechaGodzilla' when no argument is present:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 say "First try-----------" ;
06 animals( 'Mimi' , 'Nikki' , 'Godzilla' );
07
08 say "Second try-----------" ;
09 animals( 'Buster' , 'Nikki' , );
10
11 sub animals ( $cat , $dog , $lizard = 'MechaGodzilla' ) {
12 say "The cat is $cat" ;
13 say "The dog is $dog" ;
14 say "The lizard is $lizard" ;
15 }

On the second try, you get the default value:

1 First try-----------
2 The cat is Mimi
3 The dog is Nikki
4 The lizard is Godzilla
5 Second try-----------
6 The cat is Buster
7 The dog is Nikki
8 The lizard is MechaGodzilla

This is only checking the number of arguments and assigning a value when the argument list is too short. If you pass undef as an argument, that's the (un)value that parameter will get:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 say "First try-----------" ;
06 animals( 'Mimi' , 'Nikki' , 'Godzilla' );
07
08 say "Second try-----------" ;
09 animals( 'Buster' , 'Nikki' , );
10
11 say "undef try-----------" ;
12 animals( 'Buster' , 'Nikki' , undef );
13
14 sub animals ( $cat , $dog , $lizard = 'MechaGodzilla' , $bird = 'Poppy' ) {
15 say "The cat is $cat" ;
16 say "The dog is $dog" ;
17 say "The lizard is $lizard" ;
18 say "The bird is $bird" ;
19 }

The undef does not trigger a default value, which may surprise many of you. Notice the third, "undef try" where $lizard gets no value:

01 First try-----------
02 The cat is Mimi
03 The dog is Nikki
04 The lizard is Godzilla
05 The bird is Poppy
06 Second try-----------
07 The cat is Buster
08 The dog is Nikki
09 The lizard is MechaGodzilla
10 The bird is Poppy
11 undef try-----------
12 The cat is Buster
13 The dog is Nikki
14 The lizard is
15 The bird is Poppy

You can also have a null default value. You might want to have one optional parameter but not assign a value if the argument list isn't long enough. This signature allows one or two arguments, with no defaults:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 say "First try-----------" ;
06 animals( 'Mimi' , 'Nikki' );
07
08 say "Second try-----------" ;
09 animals( 'Buster' );
10
11 sub animals ( $cat , $= ) { # second argument is optional
12 say "The cat is $cat" ;
13 say "Second argument is $_[1]" if $ #_ == 1;
14 }

You see that the second argument only exists if you specify it yourself:

1 First try-----------
2 The cat is Mimi
3 Second argument is Nikki
4 Second try-----------
5 The cat is Buster

These default values don't work with slurpy types, though. Perl will complain at compile-time. If you want that sort of thing, though, you can make the argument a scalar and assign an array or hash reference to it:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 animals( 'Buster' );
06
07 sub animals ( $cat , $hash ={} ) { # hashref argument is optional
08 say "The cat is $cat" ;
09 ...;
10 }
Fancy optional values

So far your defaults have been simple values, but you can use Perl. That means you can do almost anything. This one uses the value in another variable and increments it as it assigns defaults:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 animals( 'Mimi' );
06 animals( 'Buster' );
07
08 {
09 my $auto_id = 0;
10 sub animals ( $cat , $id = ++ $auto_id ) {
11 say "$id: The cat is $cat" ;
12 }
13 }

Each cat automatically gets its own sequence value since the animals subroutine closed over $auto_id :

1 1: The cat is Mimi
2 2: The cat is Buster

However, you can't do something tricky to bring $auto_id into the subroutine since the parser doesn't know about the variable soon enough. Neither of these work:

1 sub animals ( $cat , $id = do { state $auto_id = 0; $auto_id ++ } ) {
2 say "$auto_id: The cat is $cat" ;
3 }
4
5 sub animals ( $cat , $id = $auto_id ++ ) {
6 state $auto_id ++;
7 say "$auto_id: The cat is $cat" ;
8 }

You can make the default value a call to a subroutine:

01 use v5.20;
02 use feature qw(signatures);
03 no warnings qw(experimental::signatures);
04
05 animals( 'Mimi' );
06 animals( 'Buster' );
07
08 sub animals ( $cat , $auto_id = get_id() ) {
09 say "$auto_id: The cat is $cat" ;
10 }
11
12 sub get_id () {
13 state $id = 0;
14 ++ $id ;
15 }
Method signatures

My favorite part of signatures is that they work with methods. This doesn't mean that we have multi-dispatch in Perl (yet) (well, Perl 6 does but that's a different language). The signatures aren't any different; they follow all the same rules:

01 use v5.20;
02
03 package Local::Animals {
04 use feature qw(signatures);
05 no warnings qw(experimental::signatures);
06
07 sub new ( $class , $args = { 'name' => 'Buster' } ) {
08 bless $args , $class
09 }
10
11 sub name ( $self ) {
12 $self ->{name};
13 }
14 }
15
16 my $cat = Local::Animals->new;
17 say "Cat is " , $cat ->name;
A quick guide
Exactly zero arguments - empty signature ()
Exactly one named argument ($cat)
Zero or one arguments, with no default, unnamed ($=)
Zero or one arguments, with no default, named ($cat=)
Zero or one arguments, with a default ($cat='Buster')
Exactly two arguments, ($cat, $dog)
Two or more arguments, any number ($cat, $dog, @)
Two or more arguments, but an even number ($cat, $dog, %)
Two or more arguments, slurping rest into an array ($cat, $dog, @animals)
Two or more arguments, slurping rest into an hash ($cat, $dog, %animals)
Two, three, or four arguments, no defaults ($cat, $dog, $=, $=)
Two, three, or four arguments, one default ($cat, $dog, $lizard='Godzilla', $=)
Class method ( $class, ... )
Object method ( $self, ... )
Things to Remember

  1. LL April 16, 2015 at 6:43 pm

    Is there any way to introspect the subroutine reference to see the names and types of its arguments?

  2. Philippe July 12, 2015 at 11:05 am

    After playing a bit with this feature, it seems that signatures take a copy of @_ rather than aliasing it.

    So they don't provide an elegant replacement to:

    1 sub swap($$) {
    2 for my $x ( $_ [0] ) { for my $y ( $_ [1] ) {
    3 ( $x , $y ) = ( $y , $x );
    4 }}
    5 }

    I was expecting signatures to do aliasing of @_ , not copying.

    • brian d foy July 21, 2015 at 9:53 pm

      Although there is a new Perl feature to alias different names to the same data, I did not expect signatures to alias data. I don't see how that would work, either. I think there would be more confusion that way.

  3. Philippe July 12, 2015 at 11:09 am

    Also the single-line constraint can become a problem with code readability (if one wants to comment the parameters) and can be easily broken by perltidy unfortunately.

  4. zdm December 2, 2015 at 4:47 am

    Subroutine signatures is an excellent feaature, but possibility to make aliases is highly required.

    For example:

    sub ( $a, \$b, \@c ), where

    $a – is a copy of $_[0];
    $b – alias for $_[1];
    @c – ($_[2] .. $#_ );

    For \%hash I don't know what to do, maybe this can be left unimplemented.

    Maybe you can suggest this for perl core devs?

  5. Johan Vromans December 26, 2015 at 7:51 pm

    I had really hoped that there was auto-self support for methods. E.g.,

    method name { $self->{name} }

    or

    sub name : method { $self->{name} }

  6. Tiago Peczenyj December 28, 2016 at 3:05 pm

    Why this feature is still considered as experimental?

    • brian d foy January 3, 2017 at 7:18 pm

      The subroutine signature feature has several more things waiting for implementation and I think they want to figure that stuff out before they make it stable.

  7. Narbey Derbekyan June 25, 2018 at 1:53 pm

    Hello,

    What is the future or roadmap of signatures? As of now 5.26 is out and the perldeltas mention speed improvements. It sounds like signatures are here to stay, but is it still experimental? How heavily can we rely on it when using perl 5.22 for example.

    • brian d foy August 8, 2018 at 2:34 pm

      I haven't kept up with the state of signatures. They are still experimental because there are a few more features they'd like to squeeze into them. That might change the current syntax and they don't want to handcuff themselves to that. I think they're pretty close to how they'll end up though. At least I hope so because I use them almost everywhere!

      • Narbey Derbekyan August 8, 2018 at 5:24 pm

        Thank you for the response. I'm hoping the simple use cases stay as they appear to be very useful. Specially for methods.

[Sep 01, 2020] My Perl Wishlist- Invariant Sigils (Part 1)

Sep 01, 2020 | www.perl.com

My Perl Wishlist: Invariant Sigils (Part 1)

Oct 27, 2019 by Christopher White

Pop quiz! Q: What was my mistake in this line?

is %HASH{answer}, 'forty-two', '%HASH properly filled';

A: I had the answer right, but I messed up the sigil on HASH . It should be:

is $HASH{answer}, 'forty-two', '%HASH properly filled';
#  ^ $, not %

Unfortunately, on Perl v5.20+, both statements work the same way! I didn't catch the problem until I shipped this code and cpantesters showed me my mistake. It was an easy fix, but it reminded me that Perl's variant sigils can trip up programmers at any level. If I could change one thing about Perl 5, I would change to invariant sigils.

The current situation

In Perl, the sigil tells you how many things to expect . Scalars such as $foo are single values. Any single value in an array @foo or hash %foo , since it is only one thing, also uses $ , so $foo , @foo , and %foo could all refer to different pieces of the same variable -- or to different variables. This technique of "variant sigils" works, but confuses new Perl users and tripped up yours truly. To know what you are accessing in an array or hash, you have to look at both the sigil and the brackets. As a reminder:

Sigil No brackets [ ] (array access) { } (hash access)
$ $z : a scalar, i.e., a single value $z[0] : the first element of array @z $z{0} : the value in hash %z at key "0"
@ @z : An array, i.e., a list of value(s) @z[0, 1] : the list ($z[0], $z[1]) of two elements from @z (an "array slice") @z{0, "foo"} : the list ($z{0}, $z{foo}) of two elements from hash %z
% %z : A hash, i.e., a list of key/value pair(s) %z[0, 1] : the list (0, $z[0], 1, $z[1]) of keys and two values from array @z (a "hash slice") %z{0, "foo"} : the list ("0", $z{0}, "foo", $z{foo}) of keys and values from hash %z
Make the sigils part of the name

To save myself from repeating my errors, I'd like the sigil to be part of a variable's name. This is not a new idea; scalars work this way in Perl, bash, and Raku ( formerly Perl 6 ). That would make the above table look like:

Sigil No brackets [ ] (array access) { } (hash access)
$ $z : a scalar, i.e., a single value $z[0] : N/A $z{0} : N/A
@ @z : An array, i.e., a list of value(s) @z[0] : the first element of @z @z{0} : N/A
% %z : A hash, i.e., a list of key/value pair(s) %z[0] : N/A %z{0} : the value in hash %z at key 0

Simpler! Any reference to @z would always be doing something with the array named @z .

But what about slices?

Slices such as @z[0,1] and %z{qw(hello there)} return multiple values from an array or hash. If sigils @ and % are no longer available for slicing, we need an alternative. The Perl family currently provides two models: postfix dereferencing ("postderef") syntax and postfix adverbs.

Perl v5.20+ support postderef , which gives us one option. Postderef separates the name from the slice:

# Valid Perl v5.20+
$hashref->{a};      # Scalar, element at index "a" of the hash pointed to by $hashref
$hashref->@{a};     # List including the "a" element of the hash pointed to by $hashref
$hashref->%{a};     # List including the key "a" and the "a" element of the hash pointed to by $hashref

The type of slice comes after the reference, instead of as a sigil before the reference. With non-references, that idea would give us slice syntax such as @array@[1,2,3] or %hash%{a} .

Raku gives us another option: "adverbs" such as :kv . For example:

# Valid Raku
%hash{"a"}          # Single value, element at index "a" of %hash
%hash{"a"}:v;       # The same --- just the value
%hash{"a"}:kv;      # The list including key "a" and the value of the "a" element of %hash

The adverb (e.g., :kv ) goes in postfix position, immediately after the brackets or braces. Following this model, slices would look like @array[1,2,3]:l or %hash{a}:kv . (For clarity, I propose :l , as in l ist, instead of Raku's :v . Raku's :v can return a scalar or a list.)

So, the choices I see are (postderef-inspired / Raku-inspired):

What you want No subscript [ ] access { } access
Scalar $z : a scalar, i.e., a single value @z[0] : a single value from an array %z{0} : the value in hash %z at key "0"
List of values @z : an array, i.e., a list of value(s) @z@[0, 1] / @z[0, 1]:l : the list currently written ($z[0], $z[1]) %z@{0, "foo"} / %z{0, "foo"}:l : the list currently written ($z{0}, $z{foo})
List of key/value pairs %z : a hash, i.e., a list of key/value pair(s) @z%[0, 1] / @z[0, 1]:kv : the list currently written (0, $z[0], 1, $z[1]) %z%{0, "foo"} / %z{0, "foo"}:kv : the list currently written ("0", $z{0}, "foo", $z{foo})
You can't always get what you want

I prefer the adverb syntax. It is easy to read, and it draws on all the expertise that has gone into the design of Raku. However, my preference has to be implementable. I'm not convinced that it is without major surgery.

The Perl parser decides how to interpret what is inside the brackets depending on the context provided by the slice. The parser interprets the ... in @foo[...] as a list ( ref ). In $foo[...] , the parser sees the ... as a scalar expression ( ref ). For any slice syntax, the Perl parser needs to know the desired type of result while parsing the subscript expression. The adverb form, unfortunately, leaves the parser guessing until after the subscript is parsed.

You can, in fact, hack the Perl parser to save the subscript until it sees a postfix adverb. The parser can then apply the correct context. I wrote a proof-of-concept for @arr[expr]:v . It doesn't execute any code, but it does parse a postfix-adverb slice without crashing! However, while writing that code, I ran across a surprise: new syntax isn't tied to a use v5.xx directive.

It turns out the Perl parser lets code written against any Perl version use the latest syntax. Both of the following command lines work on Perl v5.30:

$ perl -Mstrict -Mwarnings -E 'my $z; $z->@* = 10..20'
#                           ^ -E: use all the latest features
$ perl -Mstrict -Mwarnings -e 'my $z; $z->@* = 10..20'   # (!!!)
#                           ^ -e: not the latest features

The second command line does not use v5.30 , so you can't use say (introduced in v5.10). However, you can use postderef (from v5.20)!

Because the parser lets old programs use new syntax, any proposed addition to Perl's syntax has to be meaningless in all previous Perl versions. A postfix adverb fails this test. For example, the following is a valid Perl program:

sub kv { "kv" }
my @arr = 10..20;
print 1 ? @arr[1,2]:kv;
        # ^^^^^^^^^^^^ valid Perl 5 syntax, but not a slice :(
print "\n";

My preferred slice syntax could change the meaning of existing programs, so it looks like I can't get my first choice.

Next Steps

This is not the end of the story! In Part 2, I will dig deeper into Perl's parser and tokenizer. I will share some surprises I discovered while investigating postderef. I will then describe a possible path to invariant sigils and the simplicity they can provide.

[Sep 01, 2020] How to get a slice of an array or an array reference-

Sep 01, 2020 | perlmaven.com

How to get a slice of an array or an array reference?

Once you are done check out the other resources you can find on this site and consider supporting me via Patreon .

Given an array listing rulers in the Kingdom of Jerusalem like this one: @kings = ('Baldwin', 'Melisende', 'Fulk', 'Amalric', 'Guy', 'Conrad') . How can we create one that is built from the 2nd, the 4th and then the 1st element?

One solution is:

@names = ($kings[2], $kings[4], $kings[1])

The other, the simpler solution is to use array slices:

@names = @kings[2,4,1]

In this case we use the @ prefix of the array and provide several indexes. If you are familiar with arrays in Perl , you surely remember that when we talk about the whole array we put @ in front of the name, but when we talk about a single element of an array we replace the @ sigil by the $ sigil and put square brackets at the end.

When we want create a list of one or more of the elements of the array we use the @ sigil again, as it represents "plural" and then we put one or more indexes in the square brackets after the name of the array.

See the full example here:

examples/array_slice.pl

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. my @kings = ( 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' );
  5. my @names = ( $kings [ 2 ], $kings [ 4 ], $kings [ 1 ]);
  6. say join ', ' , @names ; # Fulk, Guy, Melisende
  7. my @slice = @kings [ 2 , 4 , 1 ];
  8. say join ', ' , @slice ; # Fulk, Guy, Melisende
Scalar value @kings[2] better written as $kings[2]

This warning will appear if you try to use an array slice with a single index as in this example:

my @s = @kings[2];

This is how splain explains the warning:

Scalar value @kings[2] better written as $kings[2] at array_slice.pl line 14 (#1)
    (W syntax) You've used an array slice (indicated by @) to select a
    single element of an array.  Generally it's better to ask for a scalar
    value (indicated by $).  The difference is that $foo[&bar] always
    behaves like a scalar, both when assigning to it and when evaluating its
    argument, while @foo[&bar] behaves like a list when you assign to it,
    and provides a list context to its subscript, which can do weird things
    if you're expecting only one subscript.

On the other hand, if you were actually hoping to treat the array element as a list, you need to look into how references work, because Perl will not magically convert between scalars and lists for you. See perlref.

If you would like to create a new array using a single element of another array then you should probably write:

my @s = $kings[2];

or if you want to make sure readers of your code won't be surprised by the assignment of a scalar to an array, then you can even put parentheses around the value.

my @s = ($kings[2]);

Slice of an array reference

If we have out data in an ARRAY reference and not in an array, the code will be a bit more complex:

In this case we have a variable called $kings which is a reference to an array.

In the plain version, when we use individual elements we just need to dereference the ARRAY reference for each individual element.

my @names = ($kings->[2], $kings->[4], $kings->[1]);

If we would like to use the array slice syntax then first we need to dereference the whole array putting the @ sigil in-front of the reference: @$kings , but then we can simply put the square brackets behind that construct: my @slice = @$kings[2,4,1]; though I think I prefer the version when we put curly braces around the reference, thereby making it clear that it is a single unit of expression:

my @slice = @{$kings}[2,4,1];

The full example can be seen here:

examples/array_ref_slice.pl

  1. use strict ;
  2. use warnings ;
  3. use 5.010 ;
  4. my $kings = [ 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' ];
  5. my @names = ( $kings ->[ 2 ], $kings ->[ 4 ], $kings ->[ 1 ]);
  6. say join ', ' , @names ; # Fulk, Guy, Melisende
  7. my @slice = @{ $kings }[ 2 , 4 , 1 ];
  8. say join ', ' , @slice ; # Fulk, Guy, Melisende

[Aug 27, 2020] Rubber Duck Debugging

Notable quotes:
"... Original Credit ..."
Aug 27, 2020 | rubberduckdebugging.com

The rubber duck debugging method is as follows:

  1. Beg, borrow, steal, buy, fabricate or otherwise obtain a rubber duck (bathtub variety).
  2. Place rubber duck on desk and inform it you are just going to go over some code with it, if that's all right.
  3. Explain to the duck what your code is supposed to do, and then go into detail and explain your code line by line.
  4. At some point you will tell the duck what you are doing next and then realise that that is not in fact what you are actually doing. The duck will sit there serenely, happy in the knowledge that it has helped you on your way.

Note : In a pinch a coworker might be able to substitute for the duck, however, it is often preferred to confide mistakes to the duck instead of your coworker.

Original Credit : ~Andy from lists.ethernal.org

FAQs 4 days ago

I'd also highly recommend this chapter on debugging from Think Python book: https://greenteapress.com/thinkpython2/html/thinkpython2021.html

and this article: https://jvns.ca/blog/2019/06/23/a-few-debugging-resources/

[Aug 21, 2020] debugging - Can the Perl debugger save the ReadLine history to a file

Jan 01, 2011 | stackoverflow.com

Ask Question Asked 9 years, 2 months ago Active 6 years, 9 months ago Viewed 995 times Bright futures begin at Lutron View all 4 job openings!


bitbucket , 2011-06-21 23:35:26

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 ?

eli ,

just for anyone else looking for that: for readline to work in perl (ctrl-p / ctrl-n / ...) one has to apt-get install libterm-readline-gnu-perl (at least in debian) – eli Jun 7 '18 at 14:13

ysth ,

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 ,

@bitbucket: I've had enough problems in the past getting the built-in readline support working that I don't even bother anymore :) – ysth Jun 22 '11 at 16:59

[Aug 19, 2020] Perl splice function

Aug 19, 2020 | perldoc.perl.org

Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage

[Aug 19, 2020] How do I add an array ref to the middle of an existing array in Perl- - Stack Overflow

Jan 01, 2009 | stackoverflow.com

How do I add an array ref to the middle of an existing array in Perl? Ask Question Asked 11 years, 2 months ago Active 6 years, 7 months ago Viewed 6k times

https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html Report this ad


, 2009-06-22 03:09:37

I want to be able to place an array into an array. For example, I may have an array like this:

my @array1 = ("element 1","element 2","element 3");

Then I have another array

my $array_ref = ["this will", "go between", "element 1 and 2"];

I want to place $array_ref into the first so that the first array looks like this:

("element 1",["this will", "go between", "element 1 and 2"],"element 2","element 3")

I can't seem to do this. I looked all over Google and found nothing.

Telemachus ,

The second one is not an array. It is an array reference. – Alan Haggai Alavi Jun 22 '09 at 4:26

ysth , 2009-06-22 03:28:29

So you use splice to replace 0 elements beginning with element 1 (the second element, the first is element 0) with your desired elements:

splice( @array, 1, 0, ["this will", "go between", "element 1 and 2"] );

Or possibly you mean:

splice( @array, 1, 0, "this will", "go between", "element 1 and 2" );

if you don't want nested arrays.

Nic Gibson ,

I think he meant insert into an existing array too. Not totally clear though. – Nic Gibson Jun 22 '09 at 8:47

aks ,

The important point to remember is the distinction between () and []. '()' gives you a list of elements, for eg. (1, 2, 3) which you could then assign to an array variable as so -

my @listOfElem = (1, 2, 3);

'[]' is an array reference and returns a scalar value which you could incorporate into your list.

my $refToElem = ['a', 'b', 'c'];

In your case, if you are initializing the first array then you could simply insert the second array elements like so,

my @listOfElem = (1, 2, ['a', 'b', 'c'], 3);
#This gives you a list of "4" elements with the third
#one being an array reference

my @listOfElem = (1, 2, $refToELem, 3);
#Same as above, here we insert a reference scalar variable

my @secondListOfElem = ('a', 'b', 'c');
my @listOfElem       = (1, 2, \@secondListOfElem, 3);
#Same as above, instead of using a scalar, we insert a reference
#to an existing array which, presumably, is what you want to do.

#To access the array within the array you would write -
$listOfElem[2]->[0]  #Returns 'a'
@{listOfElem[2]}[0]  #Same as above.

If you have to add the array elements on the fly in the middle of the array then just use 'splice' as detailed in the other posts.

> ,

add a comment

brian d foy , 2009-06-22 13:36:27

This is the sort of thing you'll understand after going through the first part of Intermediate Perl , which covers references and data structures. You can also look in the Perl data structures cookbook .

In short, you store an array in another array by using a reference (which is just a scalar):

my @big_array = ( $foo, $bar, \@other_array, $baz );

In your case, you used the anonymous array constructor and just want to splice it into an existing array. There's nothing special about it being an array reference:

splice @big_array, $offset, $length, @new_items;

In your case, you wanted to start at element 1, remove 0 items, and add your reference:

splice @big_array, 1, 0, $array_ref;

> ,

add a comment

anonymous coward , 2009-06-22 03:18:52

Try having a temporary array, like this:

@temp_arr = ("this will", "go between", "element 1 and 3");
@my_arr = ("element 1", \@temp_arr, "element 3");

You can use the sub-elements like this:

print $my_arr[1]->[0]; # prints 'this will'

Refer to the subarray like this:

print @$my_arr[1]; # Right! Prints 'this willgo betweenelement 1 and 2'

# Don't do this:
print $my_arr[1]; # Wrong! Prints something like: 'ARRAY(0xDEADBEEF)'

Ape-inago ,

I agree, use references. – Ape-inago Jun 22 '09 at 3:20

Alan Haggai Alavi , 2009-06-22 04:35:10

What you have is an array and an array reference.

#!/usr/bin/perl

use strict;
use warnings;

my @array    = ("element 1","element 2","element 3");
my $arrayref = ["this will", "go between", "element 1 and 2"];

splice( @array, 1, 0, $arrayref );  # Grow the array with the list (which is $arrayref)

for ( my $i = 0; $i <= $#array; $i++ ) {
    print "\@array[$i] = $array[$i]\n";
}

> ,

add a comment

> ,

Use splice .

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @array1 = ("element 1", "element 2", "element 3");
my $array_ref = ["this will", "go between", "element 1 and 2"];
splice(@array1, 1, 0, $array_ref);
print Dumper \@array1;

This will print the following:

$VAR1 = [
          'element 1',
          [
            'this will',
            'go between',
            'element 1 and 2'
          ],
          'element 2',
          'element 3'
        ];

[Aug 17, 2020] Why split function treats single quotes literals as regex, instead of a special case-

Aug 17, 2020 | perlmonks.org

on Aug 14, 2020 at 02:21 UTC ( # 11120703 = perlquestion : print w/replies , xml ) Need Help?? likbez has asked for the wisdom of the Perl Monks concerning the following question: Reputation: 5

Edit

It looks like Perl split function treats single quotes literal semantically inconsistently with other constructs

But not always :-). For example

($line)=split(' ',$line,1)
is treated consistently (in AWK way). This is the only way I know to avoid using regex for a very common task of trimming the leading blanks.

In general, split function should behave differently if the first argument is string and not a regex. But right now single quoted literal is treated as regular expression. For example:

$line="head xxx tail";
say split('x+',$line);
will print
head  tail

Am I missing something? BTW this would be similar to Python distinguishing between split and re.split but in a more elegant, Perlish way. And a big help for sysadmins.


jwkrahn on Aug 14, 2020 at 03:33 UTC

Re: Why split function treats single quotes literals as regex, instead of a special case?

The single space character is a special case for split, anything else is treated as a regular expression, be it a string, function call, etc.

Regular expressions are also treated a bit differently than regular expressions in qr//, m// and s///.

AnomalousMonk on Aug 14, 2020 at 04:38 UTC

Re^2: Why split function treats single quotes literals as regex, instead of a special case?


by AnomalousMonk on Aug 14, 2020 at 04:38 UTC

The single space character is a special case for split ...
I.e., per split :
As another special case, split emulates the default behavior of the command line tool awk when the PATTERN is either omitted or a string composed of a single space character (such as ' ' or "\x20" , but not e.g. / / ). In this case, any leading whitespace in EXPR is removed before splitting occurs, and the PATTERN is instead treated as if it were /\s+/ ; in particular, this means that any contiguous whitespace (not just a single space character) is used as a separator.
You also write:
Regular expressions are also treated a bit differently than regular expressions in qr//, m// and s///.
I don't understand this statement. Can you elaborate? Give a man a fish : <%-{-{-{-<

jwkrahn on Aug 14, 2020 at 09:16 UTC

Re^3: Why split function treats single quotes literals as regex, instead of a special case?
by jwkrahn on Aug 14, 2020 at 09:16 UTC

The regular expression // works differently in split then elsewhere:

$ perl -le' my $x = "1234 abcd 5678"; print $& if $x =~ /[a-z]+/; print $& if $x =~ //; print map qq[ "$_"], split /[a-z]+/, $x; print map qq[ "$_"], split //, $x; ' abcd abcd "1234 " " 5678" "1" "2" "3" "4" " " "a" "b" "c" "d" " " "5" "6" "7" "8" [download]

Also, the line anchors /^/ and /$/ don't require the /m option to match lines in a string.

AnomalousMonk on Aug 14, 2020 at 18:17 UTC

Re^4: Why split function treats single quotes literals as regex, instead of a special case?
by AnomalousMonk on Aug 14, 2020 at 18:17 UTC

jcb on Aug 14, 2020 at 23:07 UTC

Re^4: Why split function treats single quotes literals as regex, instead of a special case?
by jcb on Aug 14, 2020 at 23:07 UTC

Anonymous Monk on Aug 14, 2020 at 10:02 UTC

Re: Why split function treats single quotes literals as regex, instead of a special case?

perldoc -f split

perlfan on Aug 14, 2020 at 16:51 UTC

Re: Why split function treats single quotes literals as regex, instead of a special case?

> Am I missing something?

Yes, this is Perl not Python.

> Why?

I can assert that conextually, splitting on all characters for split //, $string is a lot more meaningful than splitting on nothing and returning just the original $string . The big surprise actually happens for users (like me) who don't realize the first parameter of split is a regular expression. But that surprise quickly turns into joy .

> In general, split function should behave differently if the first argument is string and not a regex.

Should ? That's pretty presumptuous. You'll notice that Perl has FAR few built in functions (particularly string functions) than PHP, JavaScript, or Python. This is because they've all been generalized away into regular expressions. You must also understand that the primary design philosphy is more related to spoken linquistics than written code. The implication here is that humans are lazy and don't want to learn more words than they need to communicate - not true of all humans, of course. But true enough for 99% of them. This is also reflected in the Huffmanization of most Perl syntax. This refers to Huffman compression, which necessarily compresses more frequently used things (characters, words, etc) into the symbols of the smallest size. I mean Perl isn't APL, but certainly gets this idea from it.

The balkanization of built-in functions that are truly special cases of a general case is against any philosophical underpinnings that Perl follows. I am not saying it's perfect, but it is highly resistent to becoming a tower of babble. If that's your interest (not accusing you of being malicious), there are more fruitful avenues to attack Perl. Most notably, the areas of object orientation and threading. But you'll have pretty much zero success convincing anyone who has been around Perl for a while that the approach to split is incorrect .

Oh, also a string (as you're calling it) is a regular expression in the purest sense of the term . It's best described as a concatenation of a finite set of symbols in fixed ordering. For some reason a lot of people think this regex magic is only present in patterns that may have no beginning or no end, or neither. In your case it just happens to have both. Doesn't make it any less of a regular expression, though.

you !!! on Aug 14, 2020 at 19:29 UTC

Re^2: Why split function treats single quotes literals as regex, instead of a special case?


by you !!! on Aug 14, 2020 at 19:29 UTC Reputation: 5

The balkanization of built-in functions that are truly special cases of a general case is against any philosophical underpinnings that Perl follows. I am not saying it's perfect, but it is highly resistant to becoming a tower of babble. If that's your interest (not accusing you of being malicious), there are more fruitful avenues to attack Perl

I respectfully disagree. Perl philosophy states that there should be shortcuts for special cases if they are used often. That's the idea behind suffix conditionals ( return if (index($line,'EOL')>-1) ) and bash-style if statement ( ($debug) && say line; )

You also are missing the idea. My suggestion is that we can enhance the power of Perl by treating single quoted string differently from regex in split. And do this without adding to balkanization.

Balkanization of built-ins is generally what Python got having two different functions. Perl can avoid this providing the same functionality with a single function. That's the idea.

And my point is that this particular change requires minimal work in interpreter as it already treats ' ' in a special way (AWK way).

So this is a suggestion for improving the language, not for balkanization, IMHO. And intuitively it is logical as people understand (and expect) the difference in behavior between single quoted literals and regex in split. So, in a way, the current situation can be viewed as a bug, which became a feature.

perlfan on Aug 15, 2020 at 08:04 UTC

Re^3: Why split function treats single quotes literals as regex, instead of a special case?
by perlfan on Aug 15, 2020 at 08:04 UTC So, in a way, the current situation can be viewed as a bug, which became a feature.

To be fair, this is a lot of perl . But I can't rightfully assert that this behavior was unintentional, in fact it appears to be very intentional (e.g., awk emulation).

> You also are missing the idea.

My understanding is that you wish for "strings" (versus "regexes") to invoke the awk behavior of trimming leading white space. Is that right? I'm not here to judge your suggestion, but I can easily think of several reasons why adding another special case to split is not a great idea.

All I can say is you're the same guy who was looking for the trim method in Perl. If that's not a red flag for being okay with balkanization , I don't know what is.

Finally, I must reiterate. A "string" is a regular expression . The single quoted whitespace is most definitely a special exception since it is also a regular expression. You're recommending not only removing one regex from the pool of potential regexes, but an entire class of them available via quoting - i.e., fixed length strings of a fixed ordering. I am not sure how this is really a suggestion of making all quoted things not be regexes, because then how do you decide if it is "regex" or not? (maybe use a regex? xD)

Replies are listed 'Best First'.

[Aug 16, 2020] Two meanings of undef

Aug 16, 2020 | perlmonks.org

on Aug 15, 2020 at 18:21 UTC ( # 11120786 = perlquestion : print w/replies , xml ) Need Help?? likbez has asked for the wisdom of the Perl Monks concerning the following question:

The system function undef can be used on the right side of split function or array assignment to skip values that you do not need. For example:

$current_time='14:30:05'
(undef, $min, $sec)=$current_time

In this role it is similar to /dev/null in Unix.

But if used on the right side this function deletes the variable from the symbol table, For example

$line=undef; say "Does not exists" unless(defined($line));

Is this correct understanding?

[Aug 16, 2020] How to trim a line from leading and trailing blanks without using regex or non-standard modules

Aug 16, 2020 | perlmonks.org

on Aug 14, 2020 at 02:24 UTC ( # 11120704 = perlquestion : print w/replies , xml ) Need Help?? likbez has asked for the wisdom of the Perl Monks concerning the following question: Reputation: 4

Edit

Is there any way to trim both leading and trailing blanks in a text line (one of the most common operations in text processing; often implemented as trim function which BTW was present in Perl 6) without resorting to regular expressions (which are definitely an overkill for this particular purpose)? This is clearly an important special case.

So far the most common solution is to use something like $line =~ s/^\s+|\s+$//g which clearly is an abuse of regex.

See, for example, https://perlmaven.com/trim

Or install String::Util which is a not a standard module and as such creates difficulties in enterprise env.


hippo on Aug 14, 2020 at 06:46 UTC

Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules
without resorting to regular expressions (which are definitely an overkill for this particular purpose)?

Sure, just write your own function to do it. Having written that you will then come to the conclusion that regular expressions are definitely not an overkill for this particular purpose.

This is clearly an important special case. ... which clearly is an abuse of regex.

You keep using that word. I don't think it means what you think it means.

🦛

LanX on Aug 14, 2020 at 03:28 UTC

Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules

> which clearly is an abuse of regex.

Why is it an abuse of regex?

Problem is that \s is a meta character for any white-space not only blank " " , but only usable inside regex.°

So if you want the exact same semantic, it'll become far more complicated than this regex.

But better define your own trim() using a regex inside.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

°) compare Re^3: How to trim a line from leading and trailing blanks without using regex or non-standard modules

you !!! on Aug 14, 2020 at 19:39 UTC

Re^2: How to trim a line from leading and trailing blanks without using regex or non-standard modules


by you !!! on Aug 14, 2020 at 19:39 UTC Reputation: 6

So if you want the exact same semantic, it'll become far more complicated than this regex.

I agree. That's a good point. Thank you !

In other words it is not easy to design a good trim function without regex, but it is possible to design one that used regex, but treating the single quoted string as a special case

For example

trim(' ',$line)
vs
trim(/\s/.$line)
BTW this is impossible in Python which implements regex via library, unless you add a new lexical type to the Language (regex string instead of raw string that is used).

LanX on Aug 15, 2020 at 01:04 UTC

Re^3: How to trim a line from leading and trailing blanks without using regex or non-standard modules
by LanX on Aug 15, 2020 at 01:04 UTC > trim(/\s/.$line)

I doubt this is valid syntax.

you probably mean

trim( qr/\s/, $line)

see Re^3: How to trim a line from leading and trailing blanks without using regex or non-standard modules for a slightly better implementation

> this is impossible in Python

passing regex inside a string is fine in Perl, why not in Python?

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

kcott on Aug 14, 2020 at 09:35 UTC

Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules

G'day likbez ,

I will usually reach for one of Perl's string handling functions (e.g. index , rindex , substr , and so on) in preference to a regex when that is appropriate; however, in this case, I would say that the regex makes for much cleaner code.

You could implement a trim() function using the guts of this code (which uses neither a regex nor any modules, standard or otherwise):

$ perl -E ' my @x = (" a b c ", "d e f ", " g h i", "j k l", " ", ""); say "*** Initial strings ***"; say "|$_|" for @x; for my $i (0 .. $#x) { my $str = $x[$i]; while (0 == index $str, " ") { $str = substr $str, 1; } my $str_end = length($str) - 1; while ($str_end == rindex $str, " ") { $str = substr $str, 0, $str_end; --$str_end; } $x[$i] = $str; } say "*** Final strings ***"; say "|$_|" for @x; ' *** Initial strings *** | a b c | |d e f | | g h i| |j k l| | | || *** Final strings *** |a b c| |d e f| |g h i| |j k l| || || [download]

If your question was genuinely serious, please Benchmark a trim() function using something like I've provided against another trim() function using a regex. You could obviously do the same for ltrim() and rtrim() functions.

[As others have either asked or alluded to, please explain phrases such as "definitely an overkill", "important special case" and "abuse of regex". Unfortunately, use of such language makes your post come across as some sort of trollish rant -- I'm not saying that was your intent, just how it presents itself.]

-- Ken

LanX on Aug 14, 2020 at 11:22 UTC

Re^2: How to trim a line from leading and trailing blanks without using regex or non-standard modules


by LanX on Aug 14, 2020 at 11:22 UTC

I suppose your solution works only for blank " " and not for other whitespace characters like "\n"

So it's not exactly the same like with \s °

DB<11> $a="x \n \n \n " DB<12> $a =~ s/\s+$// DB<13> x $a 0 'x' DB<14> [download]

The OP should be clearer about the semantics he wants.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

see also Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules

kcott on Aug 15, 2020 at 11:02 UTC

Re^3: How to trim a line from leading and trailing blanks without using regex or non-standard modules
by kcott on Aug 15, 2020 at 11:02 UTC

G'day Rolf ,

That's a valid point. My main intent with that code was really to show the complexity of the solution when a regex or module were not used. Anyway, adding a little more complexity, you can trim whatever blanks you want:

$ perl -E ' my @blanks = (" ", "\n", "\r", "\t"); my @x = ( " a b c ", "d e f \r ", " \t g h i", "j k l", " ", "\n", "\n\nXYZ\n\n", "" ); say "*** Initial strings ***"; say "|$_|" for @x; for my $i (0 .. $#x) { my $str = $x[$i]; while (grep { 0 == index $str, $_ } @blanks) { $str = substr $str, 1; } my $str_end = length($str) - 1; while (grep { $str_end == rindex $str, $_ } @blanks) { $str = substr $str, 0, $str_end; --$str_end; } $x[$i] = $str; } say "*** Final strings ***"; say "|$_|" for @x; ' *** Initial strings *** | a b c | | e f | g h i| |j k l| | | | | | XYZ | || *** Final strings *** |a b c| |d e f| |g h i| |j k l| || || |XYZ| || [download]

You're quite correct about "The OP should be clearer ..." . The word 'blank' is often used to mean various things: a single space, multiple consecutive spaces, a whitepace character, multiple consecutive whitepace characters, and I have also seen it used to refer to a zero-length string. Similarly, the word 'space' can mean a single space, any gap between visible characters, and so on. So, as with many posts, we're left with guessing the most likely meaning from the context.

My belief, that a regex is a better option, strengthens as the complexity of the non-regex and non-module code increases. :-)

-- Ken

jwkrahn on Aug 14, 2020 at 03:58 UTC

Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules

(IMHO) the most common solution is:

s/^\s+//, s/\s+$// for $line; [download]

Marshall on Aug 14, 2020 at 04:33 UTC

Re^2: How to trim a line from leading and trailing blanks without using regex or non-standard modules


by Marshall on Aug 14, 2020 at 04:33 UTC


s/^\s+|\s+$//g has been benchmarked. And I now think this is faster and "better" than 2 statements. There is one post at Re^3: script optmization that shows some benchmarks.

This is certainly not an "abuse" of regex. This is what regex is is for! The Perl regex engine continually becomes better and usually faster between releases.

perlfan on Aug 14, 2020 at 12:23 UTC

Re: How to trim a line from leading and trailing blanks without using regex or non-standard modules

> $line =~ s/^\s+|\s+$//g which clearly is an abuse of regex.

Why do you say that?

> trim function which BTW was present in Perl 6

You say this like it's a good thing. I bet there is also one in PHP.

karlgoethebier on Aug 14, 2020 at 12:34 UTC

Re^2: How to trim a line from leading and trailing blanks without using regex or non-standard modules


by karlgoethebier on Aug 14, 2020 at 12:34 UTC

You won

"The Crux of the Biscuit is the Apostrophe"

perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});' Help

LanX on Aug 14, 2020 at 14:43 UTC

Re^3: How to trim a line from leading and trailing blanks without using regex or non-standard modules
by LanX on Aug 14, 2020 at 14:43 UTC DB<33> sub trim { $_[1] //= qr/\s/; $_[0] =~ s/^[$_[1]]+|[$_[1]]+$// + g } DB<34> $a = $b = " \n . aaa . \n " DB<35> trim $a DB<36> trim $b, " " DB<37> x $a,$b 0 '. aaa .' 1 ' . aaa . ' DB<38> [download] Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery
Replies are listed 'Best First'.

[Aug 13, 2020] https://www.perlmonks.org/?node_id=11120582

Aug 13, 2020 | www.perlmonks.org

by zapdos

on Aug 11, 2020 at 02:09 UTC ( # 11120582 = perlquestion : print w/replies , xml ) Need Help?? zapdos has asked for the wisdom of the Perl Monks concerning the following question:
$rocks[0] = 'bedrock';
$rocks[1] = 'slate';
$rocks[2]= 'lava';
$rocks[3] = 'crushed rock';
$rocks[99] = 'schist';

$#rocks = 2; # forget all rocks after 'lava'
$#rocks = 99; # add 97 undef elements (the forgotten rocks are gone forever)
So I'm following the book Learning Perl, there's this code with comments in it: If I do print $rocks[$#rocks]; it prints nothing. Why? When I comment out $#rocks = 99; it prints 'lava' and when I comment out $#rocks = 2; it prints 'schist'.

But when I maintain the two it prints nothing as I already said.

And what the comments "add 97 undef elements (the forgotten rocks are gone forever)" and "forget all rocks after 'lava'" mean?

[Aug 13, 2020] Perl: function to trim string leading and trailing whitespace

Jan 01, 2011 | stackoverflow.com

Ask Question Asked 9 years, 7 months ago Active 2 years, 11 months ago Viewed 129k times


> ,

Is there a built-in function to trim leading and trailing whitespace such that trim(" hello world ") eq "hello world" ?

Landon Kuhn , 2011-01-04 20:10:52

edited Jan 4 '11 at 20:20 asked Jan 4 '11 at 20:10 Landon Kuhn 58.5k 41 41 gold badges 98 98 silver badges 128 128 bronze badges

daxim ,

FYI: string equality in Perl is tested by the operator eq . – A. Rex Jan 4 '11 at 20:16

> ,

Here's one approach using a regular expression:
$string =~ s/^\s+|\s+$//g ;     # remove both leading and trailing whitespace

Perl 6 will include a trim function:

$string .= trim;

Source: Wikipedia

Mark Byers , 2011-01-04 20:13:55

edited Oct 28 '12 at 15:23 answered Jan 4 '11 at 20:13 Mark Byers 676k 155 155 gold badges 1464 1464 silver badges 1383 1383 bronze badges

kyle ,

I look this up about once a month. Too bad I can't upvote it each time. – kyle Oct 29 '14 at 19:31

Ether , 2011-01-04 20:33:47

This is available in String::Util with the trim method:

Editor's note: String::Util is not a core module, but you can install it from CPAN with [sudo] cpan String::Util .

use String::Util 'trim';
my $str = "  hello  ";
$str = trim($str);
print "string is now: '$str'\n";

prints:

string is now 'hello'

However it is easy enough to do yourself:

$str =~ s/^\s+//;
$str =~ s/\s+$//;

Marki555 ,

@mklement0 nor will it ever be. But this is not relevant, since everyone should be using modules from the CPAN. – Ether Jun 9 '15 at 21:12

> ,

UncleCarl ,

@Ether With all due respect, I really appreciate knowing that this is a non-core module. This post is talking about using a module in lieu of a fairly simple regex one-liner. If the module is core, I would be much more open to it. It is relevant in this case. – UncleCarl Mar 1 '18 at 16:57

> ,

There's no built-in trim function, but you can easily implement your own using a simple substitution:
sub trim {
    (my $s = $_[0]) =~ s/^\s+|\s+$//g;
    return $s;
}

or using non-destructive substitution in Perl 5.14 and later:

sub trim {
   return $_[0] =~ s/^\s+|\s+$//rg;
}

Eugene Yarmash ,

edited Aug 18 '17 at 13:50 Flow 21.4k 13 13 gold badges 89 89 silver badges 142 142 bronze badges answered Jan 4 '11 at 20:14 Eugene Yarmash 110k 29 29 gold badges 248 248 silver badges 313 313 bronze badges

> ,

add a comment

> ,

According to this perlmonk's thread :
$string =~ s/^\s+|\s+$//g;

brettkelly , 2011-01-04 20:13:55

answered Jan 4 '11 at 20:13 brettkelly 24.3k 8 8 gold badges 49 49 silver badges 66 66 bronze badges

> ,

add a comment

> ,

Complete howto in the perfaq here: http://learn.perl.org/faq/perlfaq4.html#How-do-I-strip-blank-space-from-the-beginning-end-of-a-string-

Nanne , 2011-01-04 20:15:16

edited Jan 6 '12 at 15:51 Michael Kristofik 30.2k 15 15 gold badges 69 69 silver badges 118 118 bronze badges answered Jan 4 '11 at 20:15 Nanne 60.5k 16 16 gold badges 106 106 silver badges 152 152 bronze badges

> ,

add a comment

> ,

For those that are using Text::CSV I found this thread and then noticed within the CSV module that you could strip it out via switch:
$csv = Text::CSV->new({allow_whitespace => 1});

The logic is backwards in that if you want to strip then you set to 1. Go figure. Hope this helps anyone.

Douglas ,

answered Dec 3 '14 at 16:44 Douglas 259 2 2 silver badges 15 15 bronze badges

> ,

add a comment

> ,

One option is Text::Trim :
use Text::Trim;
print trim("  example  ");

[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

Nov 14, 2019 | stackoverflow.com

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 havin