|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
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:
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:
Create a log file and write important messages to the log file
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) }
@mylist=qw(one, two, three, four);
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
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 = 1instead. That also provide a way you can debug code in BEGIN blocks (which otherwise are executed before control is given to the debugger).
$cur_date='20060325'; (year, $month, $day)=$cur_date=~/(\d{4})(\d\d)(\d\d)/;
perl -MO=Xref[,OPTIONS] scriptname.plx
# --- 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
# 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$_"; } }
link($_[0], $target); if (-e $target) { unlink($_[0]); } else { logger("SFail to move the file '$_[0]' to '$home/$_[1]/$target' \n"); return; }
if ( $new{$match}++ || !( $tags{$match} = sprintf( "%s\t%s\t?^%s\$?\n", $match, $ARGV, $_ ) ) )
|
Switchboard | ||||
Latest | |||||
Past week | |||||
Past month |
![]() |
![]() |
![]() |
Jun 04, 2021 | www.perl.com
Anything after the
__DATA__
line is not part of the program but is available to the program through the specialDATA
filehandle:#!/usr/bin/perl print "---Outputting DATA\n", <DATA>, "---Done\n"; __DATA__ Dog Cat BirdThe output shows each line after
__DATA__
:---Outputting DATA Dog Cat Bird ---DoneI typically go the other way by starting with a data file and adding a program to the top of it:
#!/usr/bin/perl use v5.26; use Text::CSV_XS; my $csv = Text::CSV_XS->new; while( my $row = $csv->getline(*DATA) ) { say join ':', $row->@[3,7]; } __DATA__ ...many CSV lines...This is the end, my friend, the ENDYou probably also know that you can use
__END__
instead. I'm used to using that because it's a holdover from Perl 4 and that's where I first learned this:#!/usr/bin/perl print "---Outputting DATA\n", <DATA>, "---Done\n"; __END__ Dog Cat BirdYou get the same output:
---Outputting DATA Dog Cat Bird ---Done... ... ...
![]() |
![]() |
![]() |
Jun 04, 2021 | www.perl.com
-x is fun
We've had fun with the
perl
interpreter and the shebang, butperl
has a-x
which is already fun by design. This option tells Perl that the program to execute is actually embedded in a larger chunk of unrelated text to ignore. Perhaps the Perl program is in the middle of an email message:"I do not know if it is what you want, but it is what you get. -- Larry Wall" #!/usr/bin/env perl print "perl -x ignores everything before shebang\n"; print <DATA>; __END__ "Fortunately, it is easier to keep an old interpreter around than an old computer. -- Larry Wall"Executing this as a program is a syntax error because the Larry Wall quote before the shebang is not valid Perl. When we execute this code with
perl -x
, everything before the shebang is ignored and it works:$ perl -x email.txt perl -x ignores everything before shebang "Fortunately, it is easier to keep an old interpreter around than an old computer. -- Larry Wall"Out of curiosity, what if we tried to go one step further? How about multiple shebangs in a file, where one of them has a
-x
:#!/usr/bin/perl -x #!/usr/bin/perlBut it only produces an error:
Can't emulate -x on #! line.There is however a trick to achieve this, by using shell
eval
. Thatperl -x
is now executed in a shell process and not interpreted by perl binary like previously.:#!/bin/sh eval 'exec perl -x $0 ${1+"[email protected]"}' die "another day"; exit 1 #!perl print "$]\n";startperlThis article would not be complete without discussing a bit about the config variable
$Config{startperl}
. This variable comes from Config.pm that provides information about configuration environment (which you also see withperl -V
):$ perl -e 'use Config; print $Config{startperl}' #!/usr/bin/perlThis is actually built during compilation from defaults or user/vendor provided configs. What if we want a different value? Simply specify the value of this during the
./Configure
step, the configure option is-Dstartperl='...'
. We then need to rebuildperl
:$ ./Configure -des -Dstartperl='#!/my/shebang' $ make test installNow our custom value is the default:
$ perl -e 'use Config; print $Config{startperl}' #!/my/shebangExtUtils::MakeMaker and Module::Build seems also to use
startperl
among other methods to fix modules shebangs.Take care to use an interpreter or a program that behaves like a
perl
interpreter! Some CPAN modules usestartperl
to write first line of generated perl tests. The/usr/bin/env
limitation still apply here.
![]() |
![]() |
![]() |
Jun 04, 2021 | www.perl.com
Create an anonymous temporary file
If I give
open
a filename of an explicitundef
and the read-write mode (+>
or+<
), Perl opens an anonymous temporary file:open my $fh, '+>', undef;Perl actually creates a named file and opens it, but immediately unlinks the name. No one else will be able to get to that file because no one else has the name for it. If I had used File::Temp , I might leave the temporary file there, or something else might be able to see it while I'm working with it.
Print to a stringIf my perl is compiled with PerlIO (it probably is), I can open a filehandle on a scalar variable if the filename argument is a reference to that variable.
open my $fh, '>', \ my $string;This is handy when I want to capture output for an interface that expects a filehandle:
something_that_prints( $fh );Now
$string
contains whatever was printed by the function. I can inspect it by printing it:say "I captured:\n$string";Read lines from a stringI can also read from a scalar variable by opening a filehandle on it.
open my $fh, '<', \ $string;Now I can play with the string line-by-line without messing around with regex anchors or line endings:
while( <$fh> ) { ... }I write about these sorts of filehandle-on-string tricks in Effective Perl Programming .
Make a pipelineMost Unix programmers probably already know that they can read the output from a command as the input for another command. I can do that with Perl's
open
too:use v5.10; open my $pipe, '-|', 'date'; while( <$pipe> ) { say "$_"; }This reads the output of the
date
system command and prints it. But, I can have more than one command in that pipeline. I have to abandon the three-argument form which purposely prevents this nonsense:open my $pipe, qq(cat '$0' | sort |); while( <$pipe> ) { print "$.: $_"; }This captures the text of the current program, sorts each line alphabetically and prints the output with numbered lines. I might get a Useless Use of cat Award for that program that sorts the lines of the program, but it's still a feature.
gzip on the flyIn Gzipping data directly from Perl , I showed how I could compress data on the fly by using Perl's gzip IO layer. This is handy when I have limited disk space:
open my $fh, '>:gzip', $filename or die "Could not write to $filename: $!"; while( $_ = something_interesting() ) { print { $fh } $_; }I can go the other direction as well, reading directly from compressed files when I don't have enough space to uncompress them first:
open my $fh, '<:gzip', $filename or die "Could not read from $filename: $!"; while( <$fh> ) { print; }Change STDOUTI can change the default output filehandle with
select
if I don't like standard output, but I can do that in another way. I can changeSTDOUT
for the times when the easy way isn't fun enough. David Farrell showed some of this in How to redirect and restore STDOUT .First I can say the "dupe" the standard output filehandle with the special
&
mode:use v5.10; open my $STDOLD, '>&', STDOUT;Any of the file modes will work there as long as I append the
&
to it.I can then re-open
STDOUT
:open STDOUT, '>>', 'log.txt'; say 'This should be logged to log.txt.';When I'm ready to change it back, I do the same thing:
open STDOUT, '>&', $STDOLD; say 'This should show in the terminal';If I only have the file descriptor, perhaps because I'm working with an old Unix programmer who thinks vi is a crutch, I can use that:
open my $fh, "<&=$fd" or die "Could not open filehandle on $fd\n";This file descriptor has a three-argument form too:
open my $fh, '<&=', $fd or die "Could not open filehandle on $fd\n";I can have multiple filehandles that go to the same place since they are different names for the same file descriptor:
use v5.10; open my $fh, '>>&=', fileno(STDOUT); say 'Going to default'; say $fh 'Going to duped version. fileno ' . fileno($fh); say STDOUT 'Going to STDOUT. fileno ' . fileno($fh);All of these print to STDOUT.
This article was originally posted on PerlTricks.com .
![]() |
![]() |
![]() |
Jan 01, 2008 | stackoverflow.com
How do I get the full path to a Perl script that is executing? Ask Question Asked 12 years, 7 months ago Active 8 months ago Viewed 189k times
https://5a0213f7409d39e4f4257675bd947b2c.safeframe.googlesyndication.com/safeframe/1-0-38/html/container.html Report this ad
Chris Madden ,
172 38I have Perl script and need to determine the full path and filename of the script during execution. I discovered that depending on how you call the script
$0
varies and sometimes contains thefullpath+filename
and sometimes justfilename
. Because the working directory can vary as well I can't think of a way to reliably get thefullpath+filename
of the script.Anyone got a solution? perl path location Share Improve this question Follow edited Feb 18 '15 at 12:18 serenesat 4,514 10 10 gold badges 32 32 silver badges 51 51 bronze badges asked Sep 17 '08 at 16:16 Chris Madden 2,202 2 2 gold badges 15 15 silver badges 11 11 bronze badges
user1210923 ,
I know this was a long time ago but I was just looking for a perl windows way of doing this and am quite happy with my solution #!/usr/bin/perl -w my @catalog=dir
; $myHome = substr($catalog[3],14); $myHome = &rtrim($myHome); print qq(<$myHome>\n); # Right trim function to remove trailing whitespace sub rtrim { my $string = shift; $string =~ s/\s+$//; return $string; } just thought I'd share – user1210923 Dec 4 '20 at 17:42Drew Stephens , 2008-09-18 07:30:54
259There are a few ways:
$0
is the currently executing script as provided by POSIX, relative to the current working directory if the script is at or below the CWD- Additionally,
cwd()
,getcwd()
andabs_path()
are provided by theCwd
module and tell you where the script is being run from- The module
FindBin
provides the$Bin
&$RealBin
variables that usually are the path to the executing script; this module also provides$Script
&$RealScript
that are the name of the script__FILE__
is the actual file that the Perl interpreter deals with during compilation, including its full path.I've seen the first three (
$0
, theCwd
module and theFindBin
module) fail undermod_perl
spectacularly, producing worthless output such as'.'
or an empty string. In such environments, I use__FILE__
and get the path from that using theFile::Basename
module:use File::Basename; my $dirname = dirname(__FILE__);Share Improve this answer Follow edited Feb 12 '12 at 2:04 SamB 8,192 5 5 gold badges 43 43 silver badges 52 52 bronze badges answered Sep 18 '08 at 7:30 Drew Stephens 15.4k 12 12 gold badges 54 54 silver badges 81 81 bronze badgesDrew Stephens ,
This is really the best solution, especially if you already have a modified $0 – Caterham Jan 8 '12 at 1:04Ovid , 2008-09-17 16:19:48
148$0 is typically the name of your program, so how about this?
use Cwd 'abs_path'; print abs_path($0);Seems to me that this should work as abs_path knows if you are using a relative or absolute path.
Update For anyone reading this years later, you should read Drew's answer . It's much better than mine. Share Improve this answer Follow edited Jul 4 '19 at 2:47 cxw 15.4k 2 2 gold badges 37 37 silver badges 69 69 bronze badges answered Sep 17 '08 at 16:19 Ovid 11.1k 7 7 gold badges 41 41 silver badges 75 75 bronze badges
GreenGiant ,
Small comment, on activestate perl on windows $0 typically contains backslashes and abs_path returned forward slashes, so a quick "tr /\//\\/;" was needed to fix it. – Chris Madden Sep 17 '08 at 17:03Mark ,
35Use File::Spec; File::Spec->rel2abs( __FILE__ );http://perldoc.perl.org/File/Spec/Unix.html Share Improve this answer Follow edited Aug 19 '13 at 21:32 the Tin Man 151k 39 39 gold badges 197 197 silver badges 279 279 bronze badges answered Sep 17 '08 at 16:31 Mark 101k 16 16 gold badges 158 158 silver badges 219 219 bronze badges
David H. ,
Then wrap in dirname() to get the absolute path - just what I needed! – David H. Oct 4 '19 at 4:03bmdhacks , 2008-09-17 16:22:39
16I think the module you're looking for is FindBin:
#!/usr/bin/perl use FindBin; $0 = "stealth"; print "The actual path to this is: $FindBin::Bin/$FindBin::Script\n";Share Improve this answer Follow answered Sep 17 '08 at 16:22 bmdhacks 15.1k 8 8 gold badges 32 32 silver badges 55 55 bronze badges> ,
Add a commentBenjamin W. Smith ,
11You could use FindBin , Cwd , File::Basename , or a combination of them. They're all in the base distribution of Perl IIRC.
I used Cwd in the past:
Cwd:
use Cwd qw(abs_path); my $path = abs_path($0); print "$path\n";Share Improve this answer Follow edited Oct 8 '08 at 7:13 brian d foy 121k 31 31 gold badges 192 192 silver badges 549 549 bronze badges answered Sep 17 '08 at 16:29 Benjamin W. Smith 512 2 2 silver badges 6 6 bronze badgesZnik ,
@bmdhacks, you're right. Presumption is, you didn't change 0$. For example you do work above as soon as script starts (in initialization block), or elsewhere when you don't change $0. But $0 is excellent way to change process description visible under 'ps' unix tool :) This can show curren process status, etc. This is depended on programmer purpose :) – Znik Mar 3 '14 at 12:24Eric Wilhelm ,
9Getting the absolute path to
$0
or__FILE__
is what you want. The only trouble is if someone did achdir()
and the$0
was relative -- then you need to get the absolute path in aBEGIN{}
to prevent any surprises.
FindBin
tries to go one better and grovel around in the$PATH
for something matching thebasename($0)
, but there are times when that does far-too-surprising things (specifically: when the file is "right in front of you" in the cwd.)
File::Fu
hasFile::Fu->program_name
andFile::Fu->program_dir
for this. Share Improve this answer Follow edited Aug 19 '13 at 21:31 the Tin Man 151k 39 39 gold badges 197 197 silver badges 279 279 bronze badges answered Sep 18 '08 at 7:45 Eric Wilhelm 483 2 2 silver badges 2 2 bronze badgesZnik ,
Is it really likely that anyone would be so foolish as to (permanently)chdir()
at compile time? – SamB Feb 12 '12 at 21:23wnoise , 2008-09-17 16:52:24
7Some short background:
Unfortunately the Unix API doesn't provide a running program with the full path to the executable. In fact, the program executing yours can provide whatever it wants in the field that normally tells your program what it is. There are, as all the answers point out, various heuristics for finding likely candidates. But nothing short of searching the entire filesystem will always work, and even that will fail if the executable is moved or removed.
But you don't want the Perl executable, which is what's actually running, but the script it is executing. And Perl needs to know where the script is to find it. It stores this in
__FILE__
, while$0
is from the Unix API. This can still be a relative path, so take Mark's suggestion and canonize it withFile::Spec->rel2abs( __FILE__ );
Share Improve this answer Follow edited Aug 19 '13 at 21:30 the Tin Man 151k 39 39 gold badges 197 197 silver badges 279 279 bronze badges answered Sep 17 '08 at 16:52 wnoise 9,310 32 32 silver badges 46 46 bronze badgesfelwithe ,
__FILE__
still gives me a relative path. i.e. '.'. – felwithe Nov 2 '16 at 21:46Sean , 2008-09-17 16:21:33
6Have you tried:
$ENV{'SCRIPT_NAME'}or
use FindBin '$Bin'; print "The script is located in $Bin.\n";It really depends on how it's being called and if it's CGI or being run from a normal shell, etc. Share Improve this answer Follow answered Sep 17 '08 at 16:21 Sean 4,433 1 1 gold badge 17 17 silver badges 17 17 bronze badges
Znik ,
$ENV{'SCRIPT_NAME'} is empty when the script is running at console – Putnik Feb 6 '14 at 14:03Matt , 2013-07-18 23:12:45
6In order to get the path to the directory containing my script I used a combination of answers given already.
#!/usr/bin/perl use strict; use warnings; use File::Spec; use File::Basename; my $dir = dirname(File::Spec->rel2abs(__FILE__));Share Improve this answer Follow answered Jul 18 '13 at 23:12 Matt 61 1 1 silver badge 1 1 bronze badge> ,
Add a commentmoritz , 2008-09-17 16:34:54
2perlfaq8 answers a very similar question with using the
rel2abs()
function on$0
. That function can be found in File::Spec. Share Improve this answer Follow edited Aug 19 '13 at 21:31 the Tin Man 151k 39 39 gold badges 197 197 silver badges 279 279 bronze badges answered Sep 17 '08 at 16:34 moritz 12.3k 1 1 gold badge 36 36 silver badges 62 62 bronze badges> ,
Add a commentdaniel souza ,
2There's no need to use external modules, with just one line you can have the file name and relative path. If you are using modules and need to apply a path relative to the script directory, the relative path is enough.
$0 =~ m/(.+)[\/\\](.+)$/; print "full path: $1, file name: $2\n";Share Improve this answer Follow answered Jul 1 '14 at 16:19 daniel souza 332 2 2 silver badges 11 11 bronze badgesKeve ,
It does not provide the proper full path of the script if you run it like "./myscript.pl", as it would only show "." instead. But I still like this solution. – Keve Jun 27 '16 at 10:12mkc , 2012-11-26 14:01:34
1#!/usr/bin/perl -w use strict; my $path = $0; $path =~ s/\.\///g; if ($path =~ /\//){ if ($path =~ /^\//){ $path =~ /^((\/[^\/]+){1,}\/)[^\/]+$/; $path = $1; } else { $path =~ /^(([^\/]+\/){1,})[^\/]+$/; my $path_b = $1; my $path_a = `pwd`; chop($path_a); $path = $path_a."/".$path_b; } } else{ $path = `pwd`; chop($path); $path.="/"; } $path =~ s/\/\//\//g; print "\n$path\n";:DD Share Improve this answer Follow answered Nov 26 '12 at 14:01 mkc 11 1 1 bronze badge
Lee Taylor ,
Please don't just answer with code. Please explain why this is the correct answer. – Lee Taylor Nov 26 '12 at 14:21Yong Li , 2011-04-01 16:27:08
1Are you looking for this?:
my $thisfile = $1 if $0 =~ /\\([^\\]*)$|\/([^\/]*)$/; print "You are running $thisfile now.\n";The output will look like this:
You are running MyFileName.pl now.It works on both Windows and Unix. Share Improve this answer Follow edited Aug 19 '13 at 21:29 the Tin Man 151k 39 39 gold badges 197 197 silver badges 279 279 bronze badges answered Apr 1 '11 at 16:27 Yong Li 11 1 1 bronze badge
> ,
Add a commentYordan Georgiev , 2011-08-09 13:36:04
0use strict ; use warnings ; use Cwd 'abs_path'; sub ResolveMyProductBaseDir { # Start - Resolve the ProductBaseDir #resolve the run dir where this scripts is placed my $ScriptAbsolutPath = abs_path($0) ; #debug print "\$ScriptAbsolutPath is $ScriptAbsolutPath \n" ; $ScriptAbsolutPath =~ m/^(.*)(\\|\/)(.*)\.([a-z]*)/; $RunDir = $1 ; #debug print "\$1 is $1 \n" ; #change the \'s to /'s if we are on Windows $RunDir =~s/\\/\//gi ; my @DirParts = split ('/' , $RunDir) ; for (my $count=0; $count < 4; $count++) { pop @DirParts ; } my $ProductBaseDir = join ( '/' , @DirParts ) ; # Stop - Resolve the ProductBaseDir #debug print "ResolveMyProductBaseDir $ProductBaseDir is $ProductBaseDir \n" ; return $ProductBaseDir ; } #eof subShare Improve this answer Follow answered Aug 9 '11 at 13:36 Yordan Georgiev 3,986 1 1 gold badge 42 42 silver badges 47 47 bronze badgesthe Tin Man ,
While a source-only answer might solve the user's question, it doesn't help them understand why it works. You've given the user a fish, but instead you should teach them HOW to fish. – the Tin Man Aug 19 '13 at 21:28Jonathan ,
0The problem with
__FILE__
is that it will print the core module ".pm" path not necessarily the ".cgi" or ".pl" script path that is running. I guess it depends on what your goal is.It seems to me that
Cwd
just needs to be updated for mod_perl. Here is my suggestion:my $path; use File::Basename; my $file = basename($ENV{SCRIPT_NAME}); if (exists $ENV{MOD_PERL} && ($ENV{MOD_PERL_API_VERSION} < 2)) { if ($^O =~/Win/) { $path = `echo %cd%`; chop $path; $path =~ s!\\!/!g; $path .= $ENV{SCRIPT_NAME}; } else { $path = `pwd`; $path .= "/$file"; } # add support for other operating systems } else { require Cwd; $path = Cwd::getcwd()."/$file"; } print $path;Please add any suggestions. Share Improve this answer Follow edited Dec 14 '13 at 0:29 answered Dec 13 '13 at 11:57 Jonathan 1,291 2 2 gold badges 19 19 silver badges 40 40 bronze badges
> ,
Add a commentPutnik ,
0Without any external modules, valid for shell, works well even with '../':
my $self = `pwd`; chomp $self; $self .='/'.$1 if $0 =~/([^\/]*)$/; #keep the filename only print "self=$self\n";test:
$ /my/temp/Host$ perl ./host-mod.pl self=/my/temp/Host/host-mod.pl $ /my/temp/Host$ ./host-mod.pl self=/my/temp/Host/host-mod.pl $ /my/temp/Host$ ../Host/./host-mod.pl self=/my/temp/Host/host-mod.plShare Improve this answer Follow answered Feb 6 '14 at 14:39 Putnik 3,538 4 4 gold badges 26 26 silver badges 43 43 bronze badgesZnik ,
What when you call symlink? Cwd works excellent with this case. – Znik Mar 3 '14 at 12:32DavidG ,
0The problem with just using
dirname(__FILE__)
is that it doesn't follow symlinks. I had to use this for my script to follow the symlink to the actual file location.use File::Basename; my $script_dir = undef; if(-l __FILE__) { $script_dir = dirname(readlink(__FILE__)); } else { $script_dir = dirname(__FILE__); }Share Improve this answer Follow answered Apr 18 '14 at 7:56 DavidG 3,113 2 2 gold badges 25 25 silver badges 41 41 bronze badges> ,
Add a commentElmar , 2014-09-04 10:32:56
0All the library-free solutions don't actually work for more than a few ways to write a path (think ../ or /bla/x/../bin/./x/../ etc. My solution looks like below. I have one quirk: I don't have the faintest idea why I have to run the replacements twice. If I don't, I get a spurious "./" or "../". Apart from that, it seems quite robust to me.
my $callpath = $0; my $pwd = `pwd`; chomp($pwd); # if called relative -> add pwd in front if ($callpath !~ /^\//) { $callpath = $pwd."/".$callpath; } # do the cleanup $callpath =~ s!^\./!!; # starts with ./ -> drop $callpath =~ s!/\./!/!g; # /./ -> / $callpath =~ s!/\./!/!g; # /./ -> / (twice) $callpath =~ s!/[^/]+/\.\./!/!g; # /xxx/../ -> / $callpath =~ s!/[^/]+/\.\./!/!g; # /xxx/../ -> / (twice) my $calldir = $callpath; $calldir =~ s/(.*)\/([^\/]+)/$1/;Share Improve this answer Follow answered Sep 4 '14 at 10:32 Elmar 1> ,
Add a commentdrjumper , 2018-10-23 08:51:38
0None of the "top" answers were right for me. The problem with using FindBin '$Bin' or Cwd is that they return absolute path with all symbolic links resolved. In my case I needed the exact path with symbolic links present - the same as returns Unix command "pwd" and not "pwd -P". The following function provides the solution:
sub get_script_full_path { use File::Basename; use File::Spec; use Cwd qw(chdir cwd); my $curr_dir = cwd(); chdir(dirname($0)); my $dir = $ENV{PWD}; chdir( $curr_dir); return File::Spec->catfile($dir, basename($0)); }Share Improve this answer Follow answered Oct 23 '18 at 8:51 drjumper 71 3 3 bronze badges> ,
Add a commentuser3228609 , 2019-10-16 15:39:42
0On Windows using
dirname
andabs_path
together worked best for me.use File::Basename; use Cwd qw(abs_path); # absolute path of the directory containing the executing script my $abs_dirname = dirname(abs_path($0)); print "\ndirname(abs_path(\$0)) -> $abs_dirname\n";here's why:
# this gives the answer I want in relative path form, not absolute my $rel_dirname = dirname(__FILE__); print "dirname(__FILE__) -> $rel_dirname\n"; # this gives the slightly wrong answer, but in the form I want my $full_filepath = abs_path($0); print "abs_path(\$0) -> $full_filepath\n";Share Improve this answer Follow edited Oct 16 '19 at 16:01 answered Oct 16 '19 at 15:39 user3228609 1 1 1 bronze badge> ,
Add a commentuser3673 , 2020-08-23 17:39:37
0use File::Basename; use Cwd 'abs_path'; print dirname(abs_path(__FILE__)) ;Drew's answer gave me:
'.'
$ cat >testdirname use File::Basename; print dirname(__FILE__); $ perl testdirname .$ perl -v This is perl 5, version 28, subversion 1 (v5.28.1) built for x86_64-linux-gnu-thread-multi][1]Share Improve this answer Follow answered Aug 23 '20 at 17:39 user3673 496 3 3 silver badges 17 17 bronze badges> ,
Add a commentuser3061015 ,
-2What's wrong with
$^X
?#!/usr/bin/env perl<br> print "This is executed by $^X\n";Would give you the full path to the Perl binary being used.
Evert Share Improve this answer Follow edited Dec 3 '13 at 11:06 Eugene Loy 11.6k 8 8 gold badges 47 47 silver badges 73 73 bronze badges answered Dec 3 '13 at 10:48 user3061015 1 2 2 bronze badges
Putnik ,
It gives path to the Perl binary whilst path to a script required – Putnik Feb 6 '14 at 14:00
![]() |
![]() |
![]() |
Oct 15, 2020 | perlmonks.org
syphilis on Oct 14, 2020 at 02:26 UTC
e: remove first and last character of stringi'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,
RobrsFalse on Oct 14, 2020 at 06:41 UTC
Re: remove first and last character of stringTo 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 stringG'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.]
-- KenAnomalousMonk 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 UTCIt'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
Give a man a fish : <%-{-{-{-<
qr/^\"(.+)\"$/
will not match and will return an empty list, leaving $got undefined.AnomalousMonk on Oct 14, 2020 at 17:17 UTC
Re: remove first and last character of stringAs 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 12, 2020 | perlmonks.org
likbez
my $a=$x=$y=$z = foo()Here my attribute does not propogate like in case of comma. It applies only to $a, right ? But now the fun starts But now the fun startsDB<3> use v5.10 DB<4> my $a=$x=$y=$z = 1 DB<5> say "|$a|$x|$y|$z|" ||1|1|1| DB<6> unless( defined($a) ){ say "a is undefined"} a is undefinedwhy $a remains uninitialized?LanX on Oct 12, 2020 at 07:22 UTC
Re^3: What's happening in this expression? > why $a remains uninitialized? It's not the same It's not the same $a The lexical scope in the debugger is limited to the The lexical scope in the debugger is limited to the The lexical scope in the debugger is limited to the eval'ed line. Skip the my to avoid this effect.Fletch on Oct 12, 2020 at 03:25 UTC ( # 11122722 = note : print w/replies , xml ) Need Help??edit
Fletch already explained it in detail
in reply to Re^2: What's happening in this expression? (Updated)
in thread What's happening in this expression?The debugger is a bad place to play with scoping like this. In effect when you evaluate single lines like this they're more like doing an eval within the scope of the program (more or less; I'm sure someone more familiar with the perl5db could give more specifics).
It's kind of like (handwaving) textually shimming in say DebugDump( eval { YOURTEXTHERE } ) into wherever you're looking at and seeing the result.
This means that your my declaration is happening inside of a transient scope (that single eval statement) and then it's going away. Since the my was affecting only $a when you check for defined-ness it fails because the package $a wasn't defined (however your modifications to $x et al changes the package versions of those and the values do persist after the statement).$ cat test.pl use 5.032; my $foo = 10; say qq{foo: $foo} $ perl -d test.pl Loading DB routines from perl5db.pl version 1.57 Editor support available. Enter h or 'h h' for help, or 'man perldebug' for more help. main::(test.pl:2): my $foo = 10; DB<1> x $foo 0 undef DB<2> n main::(test.pl:3): say qq{foo: $foo} DB<2> x $foo 0 10 DB<3> my $foo = 20 DB<4> x $foo 0 10 DB<5> my $foo = 20; say qq{foo: $foo} foo: 20 DB<6> x $foo 0 10 [download]
Simple rule of thumb I tend to follow is just don't use my (or state or our ) from the debugger command line to try and affect anything outside of that immediate command line.
The cake is a lie.
The cake is a lie.
The cake is a lie.
likbez on Oct 15, 2020 at 04:08 UTC
Re^4: What's happening in this expression? (Updated)You are right. My variables are not always treated correctly, although recently the situation improved. I remember that in the past you just can't work with my variables at all. I just have a utility that stripped my moving them to tail comments and then reversed the situation. But now the usage of my "official" as it is forced by the strict pragma. Which means that such a situation is less acceptable.
Also if you are using recursion my attribute can't be stripped at all. So this is a clear deficiently.
That's sad, because IMHO the debugger is the crown jewel of Perl language environment and remains in certain areas unmatched by competition(macros, flexibility of c command, etc.) Possibility of b lineno ($var eq "value") is indispensable for debugging complex programs. That's what I always stress in my Perl advocacy efforts" "Unmatched by competition."
So any deficiencies here are "highly undesirable."
That's, of course, raises the question of development priorities...
![]() |
![]() |
![]() |
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
- log likbez out
- likbez
- The Monastery Gates
- Seekers of Perl Wisdom
- Meditations
- Cool Uses For Perl
- Obfuscation
- Q&A
- Tutorials
- Poetry
- Reviews
- Perl News
- Donate
- Recent Threads
- Newest Nodes
- Super Search
- PerlMonks Discussion
- What's New
Discipulus IntroductionThis 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 conceptHere 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 [email protected]; 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 [email protected]; eval $code; if ( [email protected] ){ # print "\[email protected] = [email protected]"; return (0, [email protected], "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 designThe 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::CourseIn 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 )
lessonsEach 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.
testsTests 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 interactionDuring 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 ideasTesting 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 conceptFeel 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.MerijnDiscipulus on Oct 01, 2020 at 09:24 UTC
Re^2: automateaching -- part 2: proof of conceptTux ,
by Discipulus on Oct 01, 2020 at 09:24 UTCThanks 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.
- Comment on automateaching -- part 2: proof of concept
- Select or Download Code
- Send private /msg to Discipulus
Replies are listed 'Best First'.
![]() |
![]() |
![]() |
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?
an array
an array reference
A hash
A hash reference
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 ArrayReferencing 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;DereferencingDereferencing 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 ElementsThe 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 | www.geeksforgeeks.org
DB<15> b valuedirThis 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.
![]() |
![]() |
![]() |
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 7I 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 Votesikegami ,
30Perl 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 badgesikegami ,
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:19melpomene , 2017-10-03 17:00:02
9Having
.
(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 badgesmelpomene ,
@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> ,
7Perl 5.26 removed having the current working directory in
@INC
as a security measure.It's explained in the 5.26 perldelta notes .
![]() |
![]() |
![]() |
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 7I 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 Votesikegami ,
30Perl 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 badgesikegami ,
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:19melpomene , 2017-10-03 17:00:02
9Having
.
(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 badgesmelpomene ,
@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> ,
7Perl 5.26 removed having the current working directory in
@INC
as a security measure.It's explained in the 5.26 perldelta notes .
![]() |
![]() |
![]() |
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 beliefdo{}
blocks, which do NOT count as loops.) Thecontinue
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.
![]() |
![]() |
![]() |
Jan 01, 2011 | stackoverflow.com
Asked 9 years, 7 months ago
CMS , 2011-03-02 12:31:46
9 1Can 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 VotesEugene Yarmash ,
7Setting
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 badgesMark ,
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:25Mark , 2011-03-02 13:11:54
4You'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 commentzrajm , 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 usedPERL5LIB
to instructprove
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 usingPERL5LIB=~/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 thatprove
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 commentbot403 , 2011-03-02 14:44:36
0PERL5INC 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
andcpan
executables visible to your shell, you can usecpan
to install all the modules you need. I have sometimes done this for individual applications in a similar vein to using Python Virtual Environments.
![]() |
![]() |
![]() |
Jan 01, 2013 | stackoverflow.com
Evan Carroll , 2013-06-04 20:37:24
63 5I 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,
- perldelta for 5.18 , which only really mentions insofar as to say that the feature has been downgraded to experimental ?
- this nntp.perl.org post
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
, andsmartmatch
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 badgesikegami ,
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.html – daxim Jun 4 '13 at 20:40ikegami ,
37There 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:42Joel Berger , 2013-06-05 03:19:07
21Some 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 commentraina77ow ,
9Well, 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.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 :
- match a scalar against an array
- match 2 scalars, without a warning when one of the scalars is undef
- more readable switch statements, thanks to "given/when"
- When 5.18 came out, I was quite worried about the regression of smartmatch to "experimental" status, but I was confident that things would be settled in 5.20, so I decided not to upgrade (we still use 5.14). Now 5.20 is out .. and nothing has changed about smartmatch, without even a clue about how this is going to evolve.
Our servers cannot easily upgrade to 5.20, because this would throw warnings all over the place. I tried to find a way to globally turn off these warnings (like set PERL5OPT=-M-warnings=experimental::smartmatch, or PERL5OPT=-M= experimental::smartmatch ), but this doesn't work because the "no warnings" pragma is lexically scoped, so global settings are not taken into account.
So my options are :
- don't change anything, don't upgrade, and wait for 5.22, hoping that some reasonable form of smartmatch will be reintroduced into the core
- revise all source files, adding a line "use experimental qw/smartmatch/;" at the beginning of each lexical scope ... but I have no guarantee that this will still work in future versions
- revise all source files, removing the given/when/smartmatch statements and replacing them with plain old Perl, or with features from some CPAN modules like match::smart or Smart::Match ... but it would be a pity to engage in such work if regular smartmatch comes back in a future version of Perl.
- As you can see, none of these options is really satisfactory, so I would be interested in hearing if other companies are in the same situation and how they decided to handle it.
By the way, I love the new Perl way of introducing new features as "experimental", until they become stable and official ... but this only works well when the experimental status is declared from the start . The problem with smartmatch is that it had been official for several years, before being retrograted to experimental. Agreed, the full semantics of smartmatch as published in 10.0 had inconsistencies, but throwing away the whole thing is a bit too harsh -- I'm sure that many users like me would be happy with a reasonable subset of rules for matching common cases.
Thanks in advance, Laurent Dami Posted by dami at 9:07 PM13 comments:- Aaron Priven June 24, 2014 at 12:07 AM
I think this might be a good question to pose on the perl5porters mailing list.
Reply- LeoNerd June 24, 2014 at 2:55 PM
You might also like Switch::Plain
Reply- Unknown June 24, 2014 at 5:32 PM
yes, I totally cann't accept this change as a common user!
Reply- Ed Avis June 24, 2014 at 7:13 PM
I changed my code from
if ($x ~~ @a)
to
use List::AllUtils qw(any);
Reply Replies
if (any { $_ eq $x } @a)- Unknown June 30, 2014 at 2:55 PM
Why should I use List::AllUtils=any for this case?
Is it better than `if (grep { $_ eq $x } @a )` ?
- Anonymous June 30, 2014 at 5:01 PM
grep will always iterate through the entire list given. any will stop as soon as it finds a single element matching the condition, which means on average it only has to iterate through half the elements.
- Unknown July 1, 2014 at 11:14 AM
Thanks!
- Unknown July 1, 2014 at 11:16 AM
But I can't find it in docs. Sources clarify this.
- Reply
- Aaron Priven June 24, 2014 at 8:10 PM
Thanks LeoNerd. Switch::Plain is very cool, as are lots of other things on https://metacpan.org/author/MAUKE ...
Reply- Anonymous June 27, 2014 at 12:15 PM
Hey, I'm in the same boat, I've been using smartmatch for switch since appearance and I like it, it works for me. The way i deal with pragmas is that i centralize them in a custom minipackage, as in "package pragmas" and I import that, so it's easier to manage "slight incompatibilities" like these. So when p5p marked it as experimental and issued a warning for it, i just put warnings->unimport( 'experimental::smartmatch' ) if $] >= 5.018; right below the "usual" warnings->import( FATAL => 'all' ); If p5p will would rip it off entirely, I'll just fetch some variant from cpan, put it in the pragmas package and import it from there, transparently. It's annoying, but it's not p5p's responsibility to update my code, if I wanna keep up with all the goodies and advancements. Otherwise you keep the code "dead", stuck on 5.14 and that's that, it works.
Reply- Anonymous July 1, 2014 at 11:16 AM
Hi we had the same issue with pseudhashes which was an official feature until 5.10
The problem was that old systems had huge databases with old storables containing pseudohashes. there was no wayI had to write a module to serialize pseudohashes structures into plain hashes, and we then saved as hashed structured when they appreared.
Or just leave them unitl all nodes in a cluster was uploaded from the perl 5.8.9.You have to live with it, just write software that adopts.
Reply- Unknown August 27, 2015 at 4:39 PM
Hello, I may be ressurect an old post, but as written here ( http://perldoc.perl.org/perl5180delta.html#The-smartmatch-family-of-features-are-now-experimental ), it is possible to stop the warning with this command:
no if $] >= 5.018, warnings => "experimental::smartmatch";
This will may be useful for others ^^'.
Reply- LenW September 3, 2015 at 7:59 AM
Well, 5.22 is out. Has ANYTHING happened in this area?
Reply
Does anyone know how to suppress the warnings globally
(eg with an envar) ?
![]() |
![]() |
![]() |
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
, orwhen
.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.
![]() |
![]() |
![]() |
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.txtHow 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 lineJust before doing that, let's see what is really our expectation from the command line processing.
- Long names with values: we would like to be able to accept parameters with long names followed by a value. For example --to VALUE . ("Long" is relative here, it just means more than 1 character.)
- Long names without value: We would like to accept flags that by their mere existence will turn some flag on. For example --verbose .
- Short names (or single-character names) with or without values. The above two just written -t VALUE and -v .
- Combining short names: -vd should be understood as -v -d . So we want to be able to differentiate between "long names" and "multiple short names combined". The difference here is that "long names" start with double-dash -- while short names, even if several of them were combined together start with a single dash - .
- Non-affiliated values, values that don't have any name starting with a dash in front of them. For example file1.txt file2.txt .
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::LongGetopt::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 :
- use strict ;
- use warnings ;
- use 5.010 ;
- use Getopt :: Long qw ( GetOptions );
- my $source_address ;
- GetOptions ( 'from=s' => \$source_address ) or die "Usage: $0 --from NAME\n" ;
- if ( $source_address ) {
- say $source_address ;
- }
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.)
FailuresSo when will the short circuit or die kick-in?
Unknown optionIf 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 NAMEThe first line is a warning printed by GetOptions , the second line is the string we generated using die .
Option requires an argumentAnother 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 NAMEHere 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 valuesOften 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 .
- my $source_address = 'Maven' ;
- GetOptions ( 'from=s' => \$source_address ) or die "Usage: $0 --from NAME\n" ;
- if ( $source_address ) {
- say $source_address ;
- }
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 valueIn 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.
- use strict ;
- use warnings ;
- use 5.010 ;
- use Getopt :: Long qw ( GetOptions );
- my $debug ;
- GetOptions ( 'debug' => \$debug ) or die "Usage: $0 --debug\n" ;
- 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 debugThe last example shows that values placed after such name are disregarded.
Multiple flagsObviously, 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:
- use strict ;
- use warnings ;
- use 5.010 ;
- use Getopt :: Long qw ( GetOptions );
- my $debug ;
- my $source_address = 'Maven' ;
- GetOptions (
- 'from=s' => \$source_address ,
- 'debug' => \$debug ,
- ) or die "Usage: $0 --debug --from NAME\n" ;
- say $debug ? 'debug' : 'no debug' ;
- if ( $source_address ) {
- say $source_address ;
- }
Running without any parameter will leave $debug as undef and the $source_address as 'Maven':
$ perl cli.pl no debug MavenPassing --debug will set $debug to true, but will leave $source_address as 'Maven':
$ perl cli.pl --debug debug MavenPassing --from Foo will set the $source_address but leave $debug as undef :
$ perl cli.pl --from Foo no debug FooIf we provide parameters, they will both set the respective variables:
$ perl cli.pl --debug --from Foo debug FooThe order of the parameters on the command line does not matter:
$ perl cli.pl --from Foo --debug debug FooShort namesGetopt::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 FooWe can even shorten the names to a single character:
$ perl cli.pl --f Foo --d debug Fooand in that case we can even use single-dash - prefixes:
$ perl files/cli.pl -f Foo -d debug FooThese 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 NAMESingle-character optionsIn 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:
- GetOptions (
- 'from|f=s' => \$source_address ,
- 'debug|d' => \$debug ,
- ) 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);
- use Getopt :: Long qw ( GetOptions );
- Getopt :: Long :: Configure qw ( gnu_getopt );
After doing that we can now run
$ perl cli.pl -df Foo debug FooThe full version of the script with the above changes looks like this:
Non-affiliated values
- use strict ;
- use warnings ;
- use 5.010 ;
- use Getopt :: Long qw ( GetOptions );
- Getopt :: Long :: Configure qw ( gnu_getopt );
- use Data :: Dumper ;
- my $debug ;
- my $source_address = 'Maven' ;
- GetOptions (
- 'from|f=s' => \$source_address ,
- 'debug|d' => \$debug ,
- ) or die "Usage: $0 --debug --from NAME\n" ;
- say $debug ? 'debug' : 'no debug' ;
- if ( $source_address ) {
- say $source_address ;
- }
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:
- use strict ;
- use warnings ;
- use 5.010 ;
- use Getopt :: Long qw ( GetOptions );
- use Data :: Dumper ;
- my $debug ;
- my $source_address = 'Maven' ;
- GetOptions (
- 'from=s' => \$source_address ,
- 'debug' => \$debug ,
- ) or die "Usage: $0 --debug --from NAME\n" ;
- say $debug ? 'debug' : 'no debug' ;
- if ( $source_address ) {
- say $source_address ;
- }
- 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 .
AdvancedGetopt::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 | 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 UTCWe 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 ) :
- Write clearly -- don't be too clever.
- Say what you mean, simply and directly.
- ... ... ...
- Write clearly -- don't sacrifice clarity for efficiency.
- ... ... ...
- Parenthesize to avoid ambiguity.
- ... ... ...
- Make sure special cases are truly special.
- ... ... ...
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 | 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 staffby 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 | 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 UTCHad 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 | 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 1vvelox 8 points· 3 days ago
· edited 3 days ago
ncps - A handy colorized(optional) ps like utility that with search options. Also can be told to display memory/CPU summary for all matched procs.
ncnetstat - A handy colorized(optional) netstat like utility that with search options. Among other interesting features, can be told to display CPU and memory usage for process that has the connection.
piddler - Grab info from the proc table for a single PID and display it and all open files and network connections.
essearcher - A handy command line utility for searching elasticsearch and displaying the results in a nicely formatted manner. Can even me used as a nagios check. Comes with support for fail2ban, HTTP access logs, Postfix, and syslog out of the box.
Net::DHCP::Windows::Netsh::Parse - Really helps for converting Windows DHCP servers over to ISC DHCPd.
inidhcp - Helps for managing DHCP subnets... adding new ones, checking for overlap, some basic sanity checking, and generation.... I use it to basically help manage PXE boot subnets.
level 1 relishketchup 5 points· 3 days ago· edited 3 days agovvelox 4 points· 3 days agoPaws 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
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 agoI 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 agoIf 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?
![]() |
![]() |
![]() |
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 32In 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:56Michael Carman , 2008-11-17 22:54:09
121Prototypes 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.
- Parentheses are optional.
- Context is imposed on the arguments.
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:
- They have to be visible at compile-time.
- They can be bypassed.
- Propagating context to arguments can cause unexpected behavior.
- They can make it difficult to call functions using anything other than the strictly prescribed form.
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:53cjm , 2008-11-17 21:55:27
69The 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 calong 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:57Leon Timmermans ,
30I 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 badgesThe 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> ,
4Some 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 | 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:
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.sub mypush (\@@);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 ([email protected]) myjoin ":",$a,$b,$c sub mypop (\@) mypop @array sub mysplice (\@[email protected]) 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 (*;[email protected]) 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:
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 .use Symbol 'qualify_to_ref'; sub foo (*) { my $fh = qualify_to_ref(shift, caller); ... }That is, if you say:
you'll get mytime() + 2 , not mytime(2) , which is how it would be parsed without the prototype, or with a unary prototype.mytime +2;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:
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.sub try (&$) { my ($try, $catch) = @_; eval { &$try }; if ([email protected]) { local $_ = [email protected]; &$catch; } } sub catch (&) { $_[0] } try { die "phooey"; } # not the end of the function call! catch { /phooey/ and print "unphooey\n"; };[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):
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 Functionssub mygrep (&@) { my $coderef = shift; my @result; foreach $_ (@_) { push(@result, $_) if &$coderef; } return @result; }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:
In fact, all of the following functions are inlined because Perl can determine everything at compile time:sub pi () { 3.14159 } # Not exact, but close sub PI () { 4 * atan2(1, 1) } # As good as it getsIn 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 .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 } }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:
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 Prototypessub not_inlined () { return 23 if $$; }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:
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:sub func ($) { my $n = shift; print "you gave me $n\n"; }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.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!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 :
Now the compiler won't let anything by that doesn't start with a dollar sign:sub func (\$) { my $nref = shift; print "you gave me $$nref\n"; }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.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?
![]() |
![]() |
![]() |
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 theglob
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
The simplest prototype@_
. You can still play with that yourself.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 callscat
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 adie
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: [email protected]" if [email protected];
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
Mandatory, positional parameters
3
Caught error: Too many arguments for subroutine at cat.pl line 5.
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
Placeholder parameters$_
, which is experimentally lexical from a v5.10 misadventure withgiven-when
( Perl v5.16 now sets proper magic on lexical $_ and Use for() instead of given() ).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
Slurpy parameters@_
even though you haven't assigned it to a variable.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
...;
Default values (optional parameters)
3
}
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
...;
Fancy optional values
10
}
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
;
Method signatures
15
}
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;
A quick guide
17
say
"Cat is "
,
$cat
->name;
Things to Remember
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, ... )
- Subroutine signatures are experimental
- Signatures are not prototypes
- Signatures enforce the number of arguments, but at runtime
- Default values only apply to optional parameters, and only apply to parameters past the number of actual passed arguments
LL April 16, 2015 at 6:43 pmIs there any way to introspect the subroutine reference to see the names and types of its arguments?
- brian d foy May 20, 2015 at 8:19 pm
As far as I know, there's not a way to check the signature without resorting to black magic or XS, like you could with
prototype()
for the old-style prototypes.- 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.
- 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.
- brian d foy July 21, 2015 at 9:54 pm
I've never really liked specifying "doesn't break Perltidy" as a constraint. Let the tool catch up instead.
- 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?
- 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} }
- 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.
- 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 | 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 situationIn 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:Make the sigils part of the name
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
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 key0
Simpler! Any reference to
But what about slices?@z
would always be doing something with the array named@z
.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 $hashrefThe 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
@[email protected][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 %hashThe 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):
You can't always get what you want
What you want No subscript [ ]
access{ }
accessScalar $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)@[email protected][0, 1]
/@z[0, 1]:l
: the list currently written($z[0], $z[1])
%[email protected]{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})
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 ause 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 featuresThe second command line does not
use v5.30
, so you can't usesay
(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 StepsThis 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 | 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
Scalar value @kings[2] better written as $kings[2]
- use strict ;
- use warnings ;
- use 5.010 ;
- my @kings = ( 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' );
- my @names = ( $kings [ 2 ], $kings [ 4 ], $kings [ 1 ]);
- say join ', ' , @names ; # Fulk, Guy, Melisende
- my @slice = @kings [ 2 , 4 , 1 ];
- say join ', ' , @slice ; # Fulk, Guy, Melisende
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 referenceIf 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
- use strict ;
- use warnings ;
- use 5.010 ;
- my $kings = [ 'Baldwin' , 'Melisende' , 'Fulk' , 'Amalric' , 'Guy' , 'Conrad' ];
- my @names = ( $kings ->[ 2 ], $kings ->[ 4 ], $kings ->[ 1 ]);
- say join ', ' , @names ; # Fulk, Guy, Melisende
- my @slice = @{ $kings }[ 2 , 4 , 1 ];
- say join ', ' , @slice ; # Fulk, Guy, Melisende
![]() |
![]() |
![]() |
Aug 27, 2020 | rubberduckdebugging.com
The rubber duck debugging method is as follows:
- Beg, borrow, steal, buy, fabricate or otherwise obtain a rubber duck (bathtub variety).
- Place rubber duck on desk and inform it you are just going to go over some code with it, if that's all right.
- Explain to the duck what your code is supposed to do, and then go into detail and explain your code line by line.
- 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
FAQs4 days ago
If ducks are so smart, why don't we just let the ducks do all the work? It would be wonderful if this were true, but the fact is that most ducks prefer to take a mentoring role. There are a few ducks however that do choose to code, but these are the ducks that nobody hears about because they are selected for secret government projects that are highly classified in nature.
Where can I learn more about rubber duck debugging? More information can be found at wikipedia.org , lists.ethernal.org , codinghorror.com , and zenhub.com .
Where can I hire my own duck? Great question! Amazon.com hosts a wide selection of affordable ducks that have graduated with a technical degree from some of the world's leading universities.
Why does this site exist? As a young intern in 2008 I repeatedly pestered a mentor of mine similar to Kevin's Rubber Duck Story and eventually my mentor pointed me at the 2002 lists.ethernal.org post by Andy , which paraphrased a story from the 1999 book The Pragmatic Programmer . That night I ordered a rubber duck from Amazon and purchased this domain name as a way of owning up to my behavior.
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 26, 2020 | stackoverflow.com
never_had_a_name ,
How are non-capturing groups, i.e.
(?:)
, used in regular expressions and what are they good for?aliteralmind ,
This question has been added to the Stack Overflow Regular Expression FAQ , under "Groups". – aliteralmind Apr 10 '14 at 0:25Ricardo Nolde ,
Let me try to explain this with an example.
Consider the following text:
http://stackoverflow.com/ https://stackoverflow.com/questions/tagged/regexNow, if I apply the regex below over it...
(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?... I would get the following result:
Match "http://stackoverflow.com/" Group 1: "http" Group 2: "stackoverflow.com" Group 3: "/" Match "https://stackoverflow.com/questions/tagged/regex" Group 1: "https" Group 2: "stackoverflow.com" Group 3: "/questions/tagged/regex"But I don't care about the protocol -- I just want the host and path of the URL. So, I change the regex to include the non-capturing group
(?:)
.(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?Now, my result looks like this:
Match "http://stackoverflow.com/" Group 1: "stackoverflow.com" Group 2: "/" Match "https://stackoverflow.com/questions/tagged/regex" Group 1: "stackoverflow.com" Group 2: "/questions/tagged/regex"See? The first group has not been captured. The parser uses it to match the text, but ignores it later, in the final result.
EDIT:As requested, let me try to explain groups too.
Well, groups serve many purposes. They can help you to extract exact information from a bigger match (which can also be named), they let you rematch a previous matched group, and can be used for substitutions. Let's try some examples, shall we?
Imagine you have some kind of XML or HTML (be aware that regex may not be the best tool for the job , but it is nice as an example). You want to parse the tags, so you could do something like this (I have added spaces to make it easier to understand):
\<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\> or \<(.+?)\> [^<]*? \</\1\>The first regex has a named group (TAG), while the second one uses a common group. Both regexes do the same thing: they use the value from the first group (the name of the tag) to match the closing tag. The difference is that the first one uses the name to match the value, and the second one uses the group index (which starts at 1).
Let's try some substitutions now. Consider the following text:
Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.Now, let's use this dumb regex over it:
\b(\S)(\S)(\S)(\S*)\bThis regex matches words with at least 3 characters, and uses groups to separate the first three letters. The result is this:
Match "Lorem" Group 1: "L" Group 2: "o" Group 3: "r" Group 4: "em" Match "ipsum" Group 1: "i" Group 2: "p" Group 3: "s" Group 4: "um" ... Match "consectetuer" Group 1: "c" Group 2: "o" Group 3: "n" Group 4: "sectetuer" ...So, if we apply the substitution string:
$1_$3$2_$4... over it, we are trying to use the first group, add an underscore, use the third group, then the second group, add another underscore, and then the fourth group. The resulting string would be like the one below.
L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.You can use named groups for substitutions too, using
${name}
.To play around with regexes, I recommend http://regex101.com/ , which offers a good amount of details on how the regex works; it also offers a few regex engines to choose from.
Ricardo Nolde ,
@ajsie: Traditional (capturing) groups are most useful if you're performing a replacement operation on the results. Here's an example where I'm grabbing comma-separated last & first names and then reversing their order (thanks to named groups)... regexhero.net/tester/?id=16892996-64d4-4f10-860a-24f28dad7e30 – Steve Wortham Aug 19 '10 at 15:43You can use capturing groups to organize and parse an expression. A non-capturing group has the first benefit, but doesn't have the overhead of the second. You can still say a non-capturing group is optional, for example.
Say you want to match numeric text, but some numbers could be written as 1st, 2nd, 3rd, 4th,... If you want to capture the numeric part, but not the (optional) suffix you can use a non-capturing group.
([0-9]+)(?:st|nd|rd|th)?That will match numbers in the form 1, 2, 3... or in the form 1st, 2nd, 3rd,... but it will only capture the numeric part.
![]() |
![]() |
![]() |
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 toapt-get install libterm-readline-gnu-perl
(at least in debian) – eli Jun 7 '18 at 14:13ysth ,
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 | perldoc.perl.org
Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage
- splice ARRAY,OFFSET,LENGTH,LIST
- splice ARRAY,OFFSET,LENGTH
- splice ARRAY,OFFSET
- splice ARRAY
Removes the elements designated by OFFSET and LENGTH from an array, and replaces them with the elements of LIST, if any. In list context, returns the elements removed from the array. In scalar context, returns the last element removed, or undef if no elements are removed. The array grows or shrinks as necessary. If OFFSET is negative then it starts that far from the end of the array. If LENGTH is omitted, removes everything from OFFSET onward. If LENGTH is negative, removes the elements from OFFSET onward except for -LENGTH elements at the end of the array. If both OFFSET and LENGTH are omitted, removes everything. If OFFSET is past the end of the array and a LENGTH was provided, Perl issues a warning, and splices at the end of the array.
The following equivalences hold (assuming
$#a >= $i
)
- push ( @a , $x , $y ) splice ( @a , @a , 0 , $x , $y )
- pop ( @a ) splice ( @a , -1 )
- shift ( @a ) splice ( @a , 0 , 1 )
- unshift ( @a , $x , $y ) splice ( @a , 0 , 0 , $x , $y )
- $a [ $i ] = $y splice ( @a , $i , 1 , $y )
splice can be used, for example, to implement n-ary queue processing:
- sub nary_print {
- my $n = shift ;
- while ( my @next_n = splice @_ , 0 , $n ) {
- say join q{ -- } , @next_n ;
- }
- }
- nary_print ( 3 , qw(a b c d e f g h) ) ;
- # prints:
- # a -- b -- c
- # d -- e -- f
- # g -- h
Starting with Perl 5.14, an experimental feature allowed splice to take a scalar expression. This experiment has been deemed unsuccessful, and was removed as of Perl 5.24.
![]() |
![]() |
![]() |
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:26ysth , 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:47aks ,
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 commentbrian 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 commentanonymous 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:20Alan 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 | 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
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 printhead tailAm 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 UTCThe 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 UTCThe 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 UTCjcb 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 UTCAnonymous 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: 5The 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 PerlI 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)
- Comment on Why split function treats single quotes literals as regex, instead of a special case?
- Select or Download Code
- Send private /msg to likbez
Replies are listed 'Best First'.
![]() |
![]() |
![]() |
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_timeIn 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 | 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
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 moduleswithout 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 Monasteryyou !!! 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: 6So 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)vstrim(/\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 Monasterykcott 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 modulesG'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.]
-- KenLanX 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 UTCI 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 Monasterysee 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 UTCG'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. :-)
-- Kenjwkrahn 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"The Crux of the Biscuit is the Apostrophe"
by karlgoethebier on Aug 14, 2020 at 12:34 UTCperl -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
- Comment on How to trim a line from leading and trailing blanks without using regex or non-standard modules
- Select or Download Code
- Send private /msg to likbez
Replies are listed 'Best First'.
![]() |
![]() |
![]() |
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:
- log likbez out
- likbez
- The Monastery Gates
- Seekers of Perl Wisdom
- Meditations
- Cool Uses For Perl
- Obfuscation
- Q&A
- Tutorials
- Poetry
- Reviews
- Perl News
- Donate
- Recent Threads
- Newest Nodes
- Super Search
- PerlMonks Discussion
- What's New
$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?
![]() |
![]() |
![]() |
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 thattrim(" 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 badgesdaxim ,
FYI: string equality in Perl is tested by the operatoreq
. – 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 whitespacePerl 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 badgeskyle ,
I look this up about once a month. Too bad I can't upvote it each time. – kyle Oct 29 '14 at 19:31Ether , 2011-01-04 20:33:47
This is available in String::Util with thetrim
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-intrim
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 | alvinalexander.com
By Alvin Alexander. Last updated: November 21 2019 Table of Contents
- printf formatting with Perl and Java
- A summary of printf format specifiers
- Controlling integer width with printf
- Left-justifying printf integer output
- The printf integer zero-fill option
- printf integer formatting
- formatting floating point numbers with printf
- printf string formatting
- printf special characters
- 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
Back to top printf formatting with Perl and Javaprintf
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 yourprintf
knowledge is reusable, which is a good thing.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 specifiersHere's a quick summary of the available
printf
format specifiers:Back to top Controlling integer width with printf
%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 The
%3d
specifier is used with integers, and means a minimum width of three spaces, which, by default, will be right-justified:Back to top Left-justifying printf integer output
printf("%3d", 0); 0 printf("%3d", 123456789); 123456789 printf("%3d", -10); -10 printf("%3d", -123456789); -123456789 To left-justify integer output with
printf
, just add a minus sign (-
) after the%
symbol, like this:Back to top The printf integer zero-fill option
printf("%-3d", 0); 0 printf("%-3d", 123456789); 123456789 printf("%-3d", -10); -10 printf("%-3d", -123456789); -123456789 To zero-fill your
printf
integer output, just add a zero (0
) after the%
symbol, like this:Back to top printf integer formatting
printf("%03d", 0); 000 printf("%03d", 1); 001 printf("%03d", 123456789); 123456789 printf("%03d", -10); -10 printf("%03d", -123456789); -123456789 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.Back to top formatting floating point numbers with printf
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 ' Here are several examples showing how to format floating-point numbers with
printf
:Back to top printf string formatting
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' Here are several examples that show how to format string output with
printf
:Back to top printf special characters
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 ' 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:
Back to top Related printf content
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
worldTypical 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\ 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 sprintfbooks i've written
- Java String formatting with the String.format method (like 'sprintf')
- Java 'printf' - formatting output with System.out.format
- Does Scala have a String variable substitution syntax like Ruby?
- How to use multiple regex patterns with replaceAll (Java String class)
- How to generate Java FreeMarker output as a String
- Scala String.format error: overloaded method value format with alternatives
Comments
- Sanctify Yourself
- The solitude of hiking in Alaska (Seward)
- The Girl Who Loved to Dance
- A garbage dumpster in Seward, Alaska
- Tour boat, Resurrection Bay, Seward, Alaska
- Killer whales in Alaska
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!
- Log in to post comments
Submitted by Anonymous (not verified) on March 24, 2010 - 9:57pm
Permalink Cool Thanks this really helped ;)
- Log in to post comments
Submitted by Anonymous (not verified) on June 11, 2010 - 9:10pm
Permalink Great job ! Thanks ! ^^
- Log in to post comments
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.
- Log in to post comments
Submitted by Anonymous (not verified) on November 7, 2010 - 5:37am
Permalink Neeeeat! :) Really helpful! :)
- Log in to post comments
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
- Log in to post comments
is owned and operated by
Valley Programming, LLCIn regards to links to Amazon.com, As an Amazon Associate
I (Valley Programming, LLC) earn from qualifying purchasesThis 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
This website uses cookies: learn more
- 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
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"
![]() |
![]() |
![]() |
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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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.
![]() |
![]() |
![]() |
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 withrequire
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 customimport
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 quuxJon 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 themain
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::AutoExporter::Auto. this is all you need.
Tero Niemi , 2013-04-02 00:32:25
Although it is not usually wise to dump allsub
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 1Library 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 2Library 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.
![]() |
![]() |
![]() |
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 astate
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 forwomble
.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 10Even 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 10Otherwise, 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. 147zoul ,
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 completeikegami
'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"; } } # localThe 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 ifexit
is removed and ashow2
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"; } } # localAnd now the output what was expected:
After Crying SolarisBut
state
in 5.10+ is a better choice...I hope this helps!
![]() |
![]() |
![]() |
Nov 23, 2019 | ods.com.ua
CONTENTS
- What Is a Perl Module?
- Using Perl Modules: use vs. require
- The Sample Letter.pm Module
- Subroutines and Passing Parameters
- Another Sample Module: Finance
- Multiple Inheritance
- The Perl Module Libraries
- Summary
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'variableNameThe 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. requireYou 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 ModuleThe 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 1996Re: 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,
RudiousThe 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 {Subroutines and Passing Parameters
2 local($name) = shift;
3 my($phone) = shift;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: FinanceThe 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.
$ testmeIf 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.99If 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.72The 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([email protected]) {
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 = 14Average 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([email protected]@)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 = 14Average 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 PackageThe 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 $pvand 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:
$ testmeMultiple Inheritance
# ------------------------------------------------
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
# ------------------------------------------------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:
- Create a Money directory under the /usr/lib/perl5 directory.
- Copy the existing Finance.pm file into the Money subdirectory.
- Create the new Stocks.pm file in the Money subdirectory.
- Edit the Finance.pm file to use the line package Money::Finance instead of package Finance; .
- Edit scripts to use Money::Finance as the subroutine prefix instead of Finance:: .
- 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 LibrariesA 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" -printExtension ModulesExtension 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 .
SummaryThis 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 | 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
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( min );
- say min ( 10 , 3 , - 8 , 21 ); # -8
- my @prices = ( 17.2 , 23.6 , 5.50 , 74 , '10.3' );
- say min ( @prices ); # 5.5
- # Argument "2x" isn't numeric in subroutine entry at examples/min.pl line 14.
- 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 ...
minstrThere 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
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( minstr );
- 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
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( minstr );
- say minstr ( 2 , 11 , 99 ); # 11
After all internally it uses the lt operator.
maxSimilar to min just returns the biggest number.
maxstrSimilar to minstr , returns the biggest string in ASCII order.
sumThe 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
sum0
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( sum );
- say sum ( 10 , 3 , - 8 , 21 ); # 26
- my @prices = ( 17.2 , 23.6 , '1.1' );
- say sum ( @prices ); # 41.9
- my @empty ;
- # Use of uninitialized value in say at examples/sum.pl line 14.
- say sum ( @empty ); # (prints nothing)
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
product
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( sum0 );
- say sum0 ( 10 , 3 , - 8 , 21 ); # 26
- my @prices = ( 17.2 , 23.6 , '1.1' );
- say sum0 ( @prices ); # 41.9
- my @empty ;
- say sum0 ( @empty ); # 0
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
Other functions of List::Util
- use 5.010 ;
- use strict ;
- use warnings ;
- use List :: Util qw ( product );
- my @interest = ( 1.2 , 2.6 , 4 , '1.3' );
- say product ( @interest ); # 16.224
- my @empty ;
- say product ( @empty ); # 1
The module has a number of other functions that were used in various other articles:
firstfirst 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 .
anyThe 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 .
allThe 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 .
reduceThe 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
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, }; } # _directivesthe 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 spacesub _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 answerI 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 bedIn computer-speakwake_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 seefor $day in (qw( Mon Tue Wed Thu Fri )) { wake_up (); wash ($self); eat ("breakfast"); : :Or, more extreme to show the sequence of actionsfor $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 actionsfor $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 Ieat
, 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 readabilitymy $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 likego_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 | perlmonks.org
LanX (Archbishop) on Nov 20, 2019 at 15:59 UTC
Re: Replaying debugger commands from historySure!
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
- in .perldb
- or in the -e'' command line option at startup
- (update) or even inside your debugged code inside BEGIN
![]() |
![]() |
![]() |
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
Addparse_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/errorperldb: 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 rwchmod 700 ~/.perldb
, and the error went away.
![]() |
![]() |
![]() |
Nov 05, 2017 | www.quora.com
Joe Zbiciak , Employed Updated Nov 5 2017 · Author has 2k answers and 7.3m answer views
Joachim Pense , Perl is my language of choice Answered Nov 4, 2017 · Author has 6.1k answers and 7.1m answer viewsPerl 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:
- 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...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
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 viewsYou 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.
Why is Perl so hated and not commonly used?
I think there are several reasons why Perl has a lot of detractors
- Sigils . A lot of programmers seem to hate the [email protected]% 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.
- 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.
- 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.
- 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!
- 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.
- 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.)
- 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.
- 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 | 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 istestmodule
.I guess this has something to do with the way
use
d modules areeval
d as if in aBEGIN
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 usemy
, you are creating a locally scoped non-package variable. To create a package variable, you useour
and notmy
: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 blockWhen 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
Fileour
will solve your dilemma: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;Filetest.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"; testmeAnd, 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 theif
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;
anduse warnings;
is now de rigueur and for good reasons. The use ofuse strict;
anduse 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 withmy
isn't in the current package. For example, in a simple script with no modules if I declaremy $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 Iuse strict
.If I don't
use strict
and don't declaremy $greeting
, it works as I would have expected. Another way to get the intended value and not breakuse strict
is to useour $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 | 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 'sfirst
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:
- You have one array you will search repeatedly
- You always get a new array that you only need to search once
- You get very large arrays but have limited memory
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 | 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 | 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 .NAMEmodule-checkstyle - Check that your code keeps style
SYNOPSISmodule-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 | 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 | 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 .NAMEmodule-checkstyle - Check that your code keeps style
SYNOPSISmodule-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 | stackoverflow.com
- Home
- Public
- Stack Overflow
- Tags
- Users
- Jobs
- Teams What's this?
Teams
Q&A for Work
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.
Learn more- First 10 Free
- How fast is Perl's smartmatch operator when searching for a scalar in an array? Ask Question Asked 8 years, 11 months ago Active 3 years ago Viewed 5k times 18 6
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 'sfirst
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:
- You have one array you will search repeatedly
- You always get a new array that you only need to search once
- You get very large arrays but have limited memory
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 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.
![]() |
![]() |
![]() |
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
#!/usr/bin/perl.xml
files, and we want to rename them all to.html
. Easy-peasy!
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 accountProgramming and development
- Programming cheat sheets
- New Python content
- Our latest JavaScript articles
- Recent Perl posts
- Red Hat Developers Blog
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 treeNow 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.
#!/usr/bin/perlFile::Find
andFile::Slurp
are your friends!
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 anythingif ( 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 | 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 | 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:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- 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 undefUsing the return value of the undef() function:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- $dwarfs [ 3 ] = undef ;
- 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:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- undef $dwarfs [ 3 ];
- 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 spliceThe splice function can totally eliminate the value from the array:
- use Data :: Dumper qw ( Dumper );
- my @dwarfs = qw ( Doc Grumpy Happy Sleepy Sneezy Dopey Bashful );
- splice @dwarfs,3,1;
- 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 | 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 WorldOn MS Windows we must use double quotes around our code.
$ perl -e "print qq{Hello World\n}" Hello WorldInternally, 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 enabledSince 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 WorldMS Windows:
$ perl -E "say q{Hello World}" Hello WorldYou 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 loopIf 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.txtis 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.txtwhich would become
while (<>) { s/code/foobar/ print; }That will print the result to the screen.
-i for in-place editingThe 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 | 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
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = 0 ;
- $counter ++;
- return $counter ;
- }
- say count ();
- say count ();
- say count ();
- #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 3If 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 callCheck out this strange example:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = say "world" ;
- $counter ++;
- return $counter ;
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
This will print out
hello world 2 3 4showing 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
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say count ();
- say count ();
- 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
- use strict ;
- use warnings ;
- use 5.010 ;
- say "hi" ;
- {
- my $counter = say "world" ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
hi world hello 2 3 4This 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 variableThis "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:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- sub reset_counter {
- $counter = 0 ;
- }
- }
- say count ();
- say count ();
- say count ();
- reset_counter ();
- say count ();
- say count ();
1 2 3 1 2Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.
Static arrays and hashesAs 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:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub fib {
- state @y ;
- @y = ( 1 , 1 ) if not @y ; # workaround initialization
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Alternatively we could use the "old-style" static variable with the enclosing block.
Here is the example generating the Fibonacci series:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my @y = ( 1 , 1 );
- sub fib {
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
![]() |
![]() |
![]() |
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:
- use strict ;
- package VeryLongName ;
- use vars ( '$x' );
- $x = 23 ;
- 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?
ourCaveat
- use strict ;
- package VeryLongName ;
- our $x = 23 ;
- print "VeryLongName: $x\n" ;
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.
- use strict ;
- package VeryLongName ;
- our $x = 23 ;
- print "VeryLongName: $x\n" ; # VeryLongName: 23
- package main ;
- print "$x\n" ; # 23
![]() |
![]() |
![]() |
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 whatmy
is in Perl. It defines a variable that exists only in the scope of the block in which it is defined. What doesour
do? How doesour
differ frommy
?Nathan Fellman ,Nov 20, 2016 at 1:15
Great question: How doesour
differ frommy
and what doesour
do?In Summary:
Available since Perl 5,
my
is a way to declare:
- non-package variables, that are
- private,
- new ,
- non-global variables,
- separate from any package. So that the variable cannot be accessed in the form of
$package_name::variable
.
On the other hand,
our
variables are:
- package variables, and thus automatically
- global variables,
- definitely not private ,
- nor are they necessarily new; and they
- can be accessed outside the package (or lexical scope) with the qualified namespace, as
$package_name::variable
.
Declaring a variable with
our
allows you to predeclare variables in order to use them underuse strict
without getting typo warnings or compile-time errors. Since Perl 5.6, it has replaced the obsoleteuse vars
, which was only file-scoped, and not lexically scoped as isour
.For example, the formal, qualified name for variable
$x
insidepackage main
is$main::x
. Declaringour $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 usesuse strict
oruse 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 thatuse
orrequire
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 frommy
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 thatour
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 iflocal $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 meanslocal $var;
is just a declaration! Before usinglocal
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 BAZThis 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 blockIn 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 | 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 mypackage main
so that I can directly callopen
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 frommain
toA
. 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 mainYou 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 theuse
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 noimport
sub is written then theExporter
'simport
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 topush
manually to@EXPORT_OK
since this can't be in theBEGIN
phase. In the end the sub is replaced byExporter::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 | 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 sayuse Module;? Calling
use Module
from another package (sayModule::Submodule9
) will try to run theModule::import
method. Since you don't have that method, it will call theExporter::import
method, and that is where the magic that exportsModule
's variables into theModule::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 14Russell 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 | 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:
- $x = 42 ;
- 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:
- $x = 42 ;
- print "$x\n" ; # 42
- print "$main::x\n" ; # 42
The package keyword is used to switch namespaces:
- $x = 42 ;
- print "$x\n" ; # 42
- print "$main::x\n" ; # 42
- package Foo ;
- 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.
- $x = 42 ;
- print "$x\n" ; # 42
- print "$main::x\n" ; # 42
- package Foo ;
- print "Foo: $x\n" ; # Foo:
- $x = 23 ;
- 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?
- $x = 42 ;
- print "$x\n" ; # 42
- print "$main::x\n" ; # 42
- package Foo ;
- print "Foo: $x\n" ; # Foo:
- $x = 23 ;
- print "Foo: $x\n" ; # Foo 23
- print "main: $main::x\n" ; # main: 42
- print "Foo: $Foo::x\n" ; # Foo: 23
- package main ;
- print "main: $main::x\n" ; # main: 42
- print "Foo: $Foo::x\n" ; # Foo: 23
- 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 | 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 TEST1TEST2TEST3Your code actually defines two constants COLUMNS and TEST2 :-
use strict; use constant { COLUMNS => qw/ TEST1 TEST2 TEST3 /, }; my @attr = (COLUMNS); print @attr; print TEST2and gives :-
% perl test.pl TEST1TEST3
![]() |
![]() |
![]() |
Sep 30, 2019 | perldoc.perl.org
- int EXPR
- int
Returns the integer portion of EXPR. If EXPR is omitted, uses $_ . You should not use this function for rounding: one because it truncates towards
0
, and two because machine representations of floating-point numbers can sometimes produce counterintuitive results.For example,
int(-6.725/0.025)
produces -268 rather than the correct -269; that's because it's really more like -268.99999999999994315658 instead.Usually, the sprintf , printf , or the POSIX::floor and POSIX::ceil functions will serve you better than will int .
![]() |
![]() |
![]() |
Sep 24, 2019 | perldoc.perl.org
Perl 5 version 30.0 documentation warn Perl functions A-Z | Perl functions by category | The 'perlfunc' manpage
- warn LIST
Emits a warning, usually by printing it to
STDERR
.warn
interprets its operand LIST in the same way asdie
, but is slightly different in what it defaults to when LIST is empty or makes an empty string. If it is empty and [email protected] already contains an exception value then that value is used after appending"\t...caught"
. If it is empty and[email protected]
is also empty then the string"Warning: Something's wrong"
is used.By default, the exception derived from the operand LIST is stringified and printed to
STDERR
. This behaviour can be altered by installing a $SIG{__WARN__} handler. If there is such a handler then no message is automatically printed; it is the handler's responsibility to deal with the exception as it sees fit (like, for instance, converting it into a die ). Most handlers must therefore arrange to actually display the warnings that they are not prepared to deal with, by calling warn again in the handler. Note that this is quite safe and will not produce an endless loop, since__WARN__
hooks are not called from inside one.You will find this behavior is slightly different from that of $SIG{__DIE__} handlers (which don't suppress the error text, but can instead call die again to change it).
Using a
__WARN__
handler provides a powerful way to silence all warnings (even the so-called mandatory ones). An example:
- # wipe out *all* compile-time warnings
- BEGIN { $SIG { '__WARN__' } = sub { warn $_ [ 0 ] if $DOWARN } }
- my $foo = 10 ;
- my $foo = 20 ; # no warning about duplicate my $foo,
- # but hey, you asked for it!
- # no compile-time or run-time warnings before here
- $DOWARN = 1 ;
- # run-time warnings enabled after here
- warn "\$foo is alive and $foo!" ; # does show up
See perlvar for details on setting %SIG entries and for more examples. See the Carp module for other kinds of warnings using its
carp
andcluck
functions.
![]() |
![]() |
![]() |
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 ScopingIn 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 = 1Here, $x is a package variable . There are two important things to know about package variables:
- Package variables are what you get if you don't say otherwise.
- 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 PackageIf 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 TriviaThere are only three other things to know about package variables, and you might want to skip them on the first reading:
- The package with the empty name is the same as main . So $::x is the same as $main::x for any x .
- 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 .
- 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 VariablesPerl'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 undefinedThe 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.
local and my
For private variables, you must use 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 localAlways use my ; never use local .
Wasn't that easy?
Other Properties of my VariablesEvery 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 27550There'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 TriviaDeclarations
- 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.
- 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.
- 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.
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. }SummaryPackage 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
- global variable
- global
- lexical variable
- local declaration
- my
- my declaration
- my variable
- package declaration
- package qualifier
- package variable
- private variable
- scope
- use strict vars
- use vars
Notes
- 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.
- 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.
- 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 usualSo 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.
- 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 | www.tutorialspoint.com
What are Packages?
The Package Statement
- A package is a collection of code which lives in its own namespace
- A namespace is a named collection of unique variable names (also called a symbol table).
- Namespaces prevent variable name collisions between packages
- Packages enable the construction of modules which, when used, won't clobbber variables and functions outside of the modules's own namespace
package statement switches the current naming context to a specified namespace (symbol table) - If the named package does not exists, a new namespace is first created.
$i = 1; print "$i\n"; # Prints "1" package foo; $i = 2; print "$i\n"; # Prints "2" package main; print "$i\n"; # Prints "1"
- The package stays in effect until either another package statement is invoked, or until the end of the end of the current block or file.
- You can explicitly refer to variables within a package using the :: package qualifier
$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 BlocksYou 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?
- Every BEGIN block is executed after the perl script is loaded and compiled but before any other statement is executed
- Every END block is executed just before the perl interpreter exits.
- The BEGIN and END blocks are particularly useful when creating 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
- The functions require and use will load a module.
- Both use the list of search paths in @INC to find the module (you may modify it!)
- Both call the eval function to process the code
- The 1; at the bottom causes eval to evaluate to TRUE (and thus not fail)
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 FunctionA 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 TreeWhen 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/MANIFESTHere is the descritpion of these options
- -A omits the Autoloader code (best used by modules that define a large number of infrequently used subroutines)
- -X omits XS elements (eXternal Subroutine, where eXternal means external to Perl, i.e. C)
- -n specifies the name of the module
So above command creates the following structure inside Person directory. Actual result is shown above.
- Changes
- Makefile.PL
- MANIFEST (contains the list of all files in the package)
- README
- t/ (test files)
- lib/ ( Actual source code goes here
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 ModuleInstalling a Perl Module is very easy. Use the following sequence to install any Perl Module.
perl Makefile.PL make make installThe Perl interpreter has a list of directories in which it searches for modules (global array @INC)
![]() |
![]() |
![]() |
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
Perl has a largish executable memory-footprint*. If that gets in your way (which can happen in tight spaces such as semi/embedded), you've got two choices: if it's shellable code, go to bash; otherwise, port to C. Or at least, that's my decision tree, and Perl5 is my go-to language. I use bash only when I must, and I hit the books every time.
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.
*[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
![]() |
![]() |
![]() |
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 | lukesthoughtdump.blogspot.com
Sunday, August 2, 2009 Cute Perl Gem to Get the Minimum/Maximum Value Saw this little nugget on #[email protected] 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 9:41 PM
![]() |
![]() |
![]() |
Sep 19, 2019 | stackoverflow.com
List::Util's
min
andmax
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 | 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 PerlProgramming 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:
Special Characters 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. 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:
Perl True-False Comparison Operators
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 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:
Common List Functions in Perl
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 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:
Shortcuts for Character Ranges in Perl
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 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.
Perl Pattern-Matching Quantifiers
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 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 | 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 remainingmy @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 | www.dummies.com
Avoiding Common Oversights in Perl
Related Book
Perl For Dummies, 4th EditionBy 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 semicolonProbably 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 markThe 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 10This 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 fewWhen 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 42Here, 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 40Yarp! 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 | perldoc.perl.org
Starting from Perl 5.10.1 (well, 5.10.0, but it didn't work right), you can say
- 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:
- use v5.14 ;
Under the "switch" feature, Perl gains the experimental keywords
given
,when
,default
,continue
, andbreak
. Starting from Perl 5.16, one can prefix the switch keywords withCORE::
to access the feature without ause feature
statement. The keywordsgiven
andwhen
are analogous toswitch
andcase
in other languages -- thoughcontinue
is not -- so the code in the previous section could be rewritten as
- use v5.10.1 ;
- for ( $var ) {
- when ( /^abc/ ) { $abc = 1 }
- when ( /^def/ ) { $def = 1 }
- when ( /^xyz/ ) { $xyz = 1 }
- default { $nothing = 1 }
- }
The
foreach
is the non-experimental way to set a topicalizer. If you wish to use the highly experimentalgiven
, that could be written like this:
- use v5.10.1 ;
- given ( $var ) {
- when ( /^abc/ ) { $abc = 1 }
- when ( /^def/ ) { $def = 1 }
- when ( /^xyz/ ) { $xyz = 1 }
- default { $nothing = 1 }
- }
As of 5.14, that can also be written this way:
- use v5.14 ;
- for ( $var ) {
- $abc = 1 when /^abc/ ;
- $def = 1 when /^def/ ;
- $xyz = 1 when /^xyz/ ;
- default { $nothing = 1 }
- }
Or if you don't care to play it safe, like this:
- use v5.14 ;
- given ( $var ) {
- $abc = 1 when /^abc/ ;
- $def = 1 when /^def/ ;
- $xyz = 1 when /^xyz/ ;
- default { $nothing = 1 }
- }
The arguments to
given
andwhen
are in scalar context, andgiven
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 agiven
block than it does when dynamically enclosed by aforeach
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 bygiven
is merely a lexically scoped copy of the original, not a dynamically scoped alias to the original, as it would be if it were aforeach
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.
![]() |
![]() |
![]() |
May 19, 2019 | www.quora.com
- 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
) andawk
, 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
- if mkdir $directory
- then
- echo successfully created directory : $directory
- elif test - d $directory
- then
- echo pre - existing directory : $directory
- else
- echo cannot create directory : $directory
- fi
In the Bourne shell, every statement is a Unix command invocation; in this case,
test
andmkdir
. (Some commands, such astest
, were built into the shell later.) Every command will succeed or fail, so we can use it in the condition of anif
statement.Now what if we only want to print a warning when something went wrong? We can write this:
- if mkdir $directory
- then
- : # nothing
- elif test - d $directory
- then
- : # nothing
- else
- echo cannot create directory : $directory
- fi
or we can combine the two conditions:
- if mkdir $directory || test - d $directory
- then
- : # nothing
- else
- echo cannot create directory : $directory
- fi
or we can combine them even further:
- mkdir $directory ||
- test - d $directory ||
- 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 invokestest
with the arguments up to that point. So we can always replace
- test - d $directory
with
- [ - 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:
- if ( mkdir $directory )
- {
- # nothing
- } elsif (- d $directory )
- {
- # nothing
- } else {
- say "cannot create directory: $directory"
- }
or we can combine the two conditions:
- if ( mkdir $directory || - d $directory )
- {
- # nothing
- } else {
- say "cannot create directory: $directory"
- }
or we can combine them even further:
- mkdir $directory or
- - d $directory or
- 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
- if ( some test to see if we can mkdir $directory )
- then
- mkdir directory
- fi
- if ( some test to see if we managed to mkdir directory )
- then
- [...]
- 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
- mkdir $directory or
- - d $directory or
- 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 theperlcritic
utility) and consistent code formatting (theperltidy
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 | 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 weekendand 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 | gist.githubusercontent.com
#!/usr/bin/perl -w # # This script was developed by Robin Barker ([email protected]), # 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 ([email protected]) { print "reading filenames from STDIN\n" if $verbose; @ARGV = ; chop(@ARGV); } for (@ARGV) { my $was = $_; eval $op; die [email protected] if [email protected]; 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
![]() |
![]() |
![]() |
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,
- use strict;
- use warnings;
- my $x = "Hello" ;
- $main ::x = "Bye" ;
- print "$main::x\n" ; # Bye
- 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
- 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,
- 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 keywordLook at the following code,
- use strict;
- use warnings;
- use 5.010;
- sub hii {
- return "main" ;
- }
- package two;
- sub hii {
- return "two" ;
- }
- say main::hii(); # main
- say two::hii(); # two
- say hii(); # two
- package main;
- say main::hii(); # main
- say two::hii(); # two
- 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 | 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 explanationUse 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.
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- say $x ;
Perl is very nice, tells us which file generated the warning and on which line.
Only a warningAs I mentioned this is only a warning. If the script has more statements after that say statement, they will be executed:
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- say $x ;
- $x = 42 ;
- say $x ;
This will print
Use of uninitialized value $x in say at perl_warning_1.pl line 6. 42Confusing output orderBeware though, if your code has print statements before the line generating the warning, like in this example:
- use warnings ;
- use strict ;
- use 5.010 ;
- print 'OK' ;
- my $x ;
- say $x ;
- $x = 42 ;
- say $x ;
the result might be confusing.
Use of uninitialized value $x in say at perl_warning_1.pl line 7. OK 42Here, '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 bufferingIn 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.
- use warnings ;
- use strict ;
- use 5.010 ;
- $ | = 1 ;
- print 'OK' ;
- my $x ;
- say $x ;
- $x = 42 ;
- 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
- use warnings ;
- use strict ;
- use 5.010 ;
- my $x ;
- my $y = 1 ;
- if ( $y ) {
- my $x = 42 ;
- }
- 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 | stackoverflow.com
marto ,Jul 15, 2011 at 16:52
I use thisscrub
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
Inscrub
it is too late to check, if the hash has an entry for keykey
.scrub()
only sees a scalar, which isundef
, if the hash key does not exist. But a hash could have an entry with the valueundef
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 | 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, usingdefined
?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 aboutdefined
being the right way to check whether or not a variable has a value ofundef
.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 properC
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 checkif ( 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 // $bis merely equivalent to
defined $a ? $a : $band 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 | 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 ExampleHere, 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 .
- ## Declaring arrays
- my @arr1 = qw(0 10 0);
- my @arr2 = qw(0 0 20);
- [email protected] = qw(30 0 0);
- ## Merging all the single dimensional arrays
- my @final = (\@arr1, \@arr2, \@arr3);
- print "Print Using Array Index\n" ;
- for (my $i = 0; $i <= $#final; $i ++){
- # $#final gives highest index from the array
- for (my $j = 0; $j <= $#final ; $j ++){
- print "$final[$i][$j] " ;
- }
- print "\n" ;
- }
Output:
Print Using Array Index 0 10 0 0 0 20 30 0 0
Perl Multidimensional Array Initialization and Declaration ExampleIn this example we are initializing and declaring a three dimensional Perl array .
- @ array = (
- [1, 2, 3],
- [4, 5, 6],
- [7, 8, 9]
- );
- for ( $i = 0; $i < 3; $i ++) {
- for ( $j = 0; $j < 3; $j ++) {
- print "$array[$i][$j] " ;
- }
- print "\n" ;
- }
Output:
1 2 3 4 5 6 7 8 9
![]() |
![]() |
![]() |
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:
- my %hashName = (
- "key" => "value" ;
- )
Perl Hash AccessingTo access single element of hash, ($) sign is used before the variable name. And then key element is written inside {} braces.
- my %capitals = (
- "India" => "New Delhi" ,
- "South Korea" => "Seoul" ,
- "USA" => "Washington, D.C." ,
- "Australia" => "Canberra"
- );
- print "$capitals{'India'}\n" ;
- print "$capitals{'South Korea'}\n" ;
- print "$capitals{'USA'}\n" ;
- print "$capitals{'Australia'}\n" ;
Output:
New Delhi Seoul Washington, D.C. Canberra
Perl Hash IndexingHashes 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.
- my %capitals = (
- "India" => "New Delhi" ,
- "South Korea" => "Seoul" ,
- "USA" => "Washington, D.C." ,
- "Australia" => "Canberra"
- );
- # LOOP THROUGH IT
- while (( $key , $value ) = each(%capitals)){
- print $key . ", " . $value . "\n" ;
- }
Output:
Australia, Canberra India, New Delhi USA, Washington, D.C. South Korea, Seoul
Perl sorting Hash by keyYou 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.
- my %capitals = (
- "India" => "New Delhi" ,
- "South Korea" => "Seoul" ,
- "USA" => "Washington, D.C." ,
- "Australia" => "Canberra"
- );
- # Foreach loop
- foreach $key (sort keys %capitals) {
- print "$key: $capitals{$key}\n" ;
- }
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 valueHere we'll sort hash by its value elements.
- my %capitals = (
- "India" => "New Delhi" ,
- "South Korea" => "Seoul" ,
- "USA" => "Washington, D.C." ,
- "UK" => "London"
- );
- # Foreach loop
- foreach $value (sort { $capitals { $a } cmp $capitals { $b } }
- keys %capitals)
- {
- print "$value $capitals{$value}\n" ;
- }
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 ElementsTo remove a hash element, use delete() function.
Here, we have removed both the key-value pairs which were added in the last example.
- my %capitals = (
- "India" => "New Delhi" ,
- "South Korea" => "Seoul" ,
- "USA" => "Washington, D.C." ,
- "Australia" => "Canberra"
- "Germany " => " Berlin"
- " UK " => "London"
- );
- while (( $key , $value ) = each(%apitals)){
- print $key . ", " . $value . "\n" ;
- }
- #removing element
- delete ( $capitals {Germany});
- delete ( $capitals {UK});
- # Printing new hash
- print "\n" ;
- while (( $key , $value ) = each(%capitals)){
- print $key . ", " . $value . "\n" ;
- }
Output:
Australia, Canberra India, New Delhi USA, Washington D.C. South Korea, Seoul
Perl deleting Vs Undefining Hash Elementsdeleting: In deleting, key-value pair will be deleted from the hash.
Syntax:
- delete ( $hash { $key });
undef: In undef, the value will be undefined but key will remain in the hash.
Syntax:
- undef $hash { $key };
![]() |
![]() |
![]() |
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)Mark_Uplanguage ( 444809 ) , Monday December 12, 2005 @03:13PM ( #14241006 )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; }but... TIMTOWTDI...
DEBUG and print "value of blah:", $blah, $/;
;) Re:In defense of print statements ( Score: 4 , Informative)codyk ( 857932 ) , Monday December 12, 2005 @03:20PM ( #14241071 )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.
Re:In defense of print statements ( Score: 1 )licamell ( 778753 ) * , Monday December 12, 2005 @01:47PM ( #14240302 )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]use strict and Data::Dumper! ( Score: 5 , Insightful)Baron von Leezard ( 675918 ) , Monday December 12, 2005 @03:22PM ( #14241092 )#!
/usr/local/bin/perl
#
# Two things that make debugging perl easy:
#use strict;
use Data::Dumper; ›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 ;)
![]() |
![]() |
![]() |
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 successI 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); ################################### EDanny Luk ,Aug 28, 2015 at 8:39
In print statement after print just write the filehandle name which isOUTPUT
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 handleOUTPUT
, just change your twoOUTPUT
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 anEND
block:END { close(OUTPUT); }Not only because it's in your
while
loop.
![]() |
![]() |
![]() |
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 onlycperl 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 storesPL_op_type
with the type declarations of all ops.
![]() |
![]() |
![]() |
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:
- 1. Pluggability Of Perl On All Levels
- 2. Reunification Of Perl 5 & Perl 6
- 3. Runtime Performance Of C/C++ Or Faster
Perl 11 promotes ideas which will make Perl 5 pluggable at the following levels:
- Runtime Virtual Machine
- Compilation Unit Format / AST
- Source Code Syntax / Compilers
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 ProjectsThe following projects are important in reaching the vision of Perl 11:
RPerlA Restricted Perl by Will Braswell which translates a medium-magic subset of Perl 5 into C/C++ using Inline::C and Inline::CPP
cperlcperl 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
- CloudForFree.org Runs RPerl
- Austin Perl Mongers Supports Perl 11
![]() |
![]() |
![]() |
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$.
(seeperldoc 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 | nlm.nih.gov
Find articles by John M. Macdonald Paul C. BoutrosInformatics 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: [email protected] . Contributor Information .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:
Unique identifiers and version numbers for programs and libraries;
The values of parameters used to generate any given output; and
The names and version numbers of programs (however small) used to generate those outputs.
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:
- An END block is created. It will be executed when the program terminates, to write out the log information.
- Signal handlers are installed for catcheable signals - if one of them occurs, the log information will be printed out before the program terminates.
- options are set to their default values
- any env variables to control options are saved
- a copy is made of the original command line arguments for eventual logging
- the start time is recorded for eventual logging
-... (numerous other system attributes are saved for eventual logging)
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:
MODULE – Name, version, file location, and checksum for each perl library module used by the program.
INC – The search path used to find modules.
UNAME – Operating system information.
PROCn – Specific information for each processor (memory, cores, etc.)
PERL – The perl interpretor pathname.
PERLVer – The perl interpretor version.
PERLSum – Checksum of the perl interpretor binary.
libc – The version of libc used by the perl interpretor.
libcSUM – Checksum of the libc library used by the perl interpretor.
User – The user ID (and real user ID, if different) running the program.
Group – The group IDs (and real group IDs, if different) running the program.
ProgDir – The directory containing the program.
Program – The program name.
Version – The program's version.
ProgSUM – Checksum of the program file.
Args – The number and values of the command line arguments provided to the program.
Start – The time the program started running.
End – The time the program stopped running.
Elapsed – The elapsed time while the program was running.
EndStat – The program's exit status.
program-specified – Any additional info provided by program-specified callback functions.
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.
Open in a separate window
When you run it, you get two lines of output.
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:
lines beginning with a plus sign are wrapped to fit the page width
lines wrapped in angle brackets describe text that has been omitted for brevity
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
Project name: LogProgramInfo
Project Home Page: http://search.cpan.org/search?query=Log%3A%3AProgramInfo&mode=all
Operating System(s): Linux, Unix, Mac OS X (untested), Windows (untested)
Programming Language: Perl 5
Other Requirements: none
License: Perl 5 License (Artistic 1 & GPL 1)
Go to: Acknowledgements
Special thanks to Julie Livingstone and Renasha Small-O'Connor for editorial assistance. Go to: Footnotes
cc Bug Reports To: [email protected]
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: [email protected] .
Paul C. Boutros, Email: [email protected] . 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 ]
- Abstract
- Background
- Related work
- Implementation
- Results and discussion
- Log output
- Example
- Limitations
- Conclusion
- Availability and requirements
- Acknowledgements
- Footnotes
- Contributor Information
- References
Articles from Source Code for Biology and Medicine are provided here courtesy of BioMed Central
![]() |
![]() |
![]() |
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 newlineThe -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 [email protected]:/$
![]() |
![]() |
![]() |
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:3tchrist ,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
Thecaller
function will do what you are looking for:sub print_info { my ($package, $filename, $line) = caller; ... } print_info(); # prints info about this lineThis 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 | 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
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = 0 ;
- $counter ++;
- return $counter ;
- }
- say count ();
- say count ();
- say count ();
- #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 3If 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 callCheck out this strange example:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub count {
- state $counter = say "world" ;
- $counter ++;
- return $counter ;
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
This will print out
hello world 2 3 4showing 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
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say count ();
- say count ();
- 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
- use strict ;
- use warnings ;
- use 5.010 ;
- say "hi" ;
- {
- my $counter = say "world" ;
- sub count {
- $counter ++;
- return $counter ;
- }
- }
- say "hello" ;
- say count ();
- say count ();
- say count ();
hi world hello 2 3 4This 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 variableThis "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:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my $counter = 0 ;
- sub count {
- $counter ++;
- return $counter ;
- }
- sub reset_counter {
- $counter = 0 ;
- }
- }
- say count ();
- say count ();
- say count ();
- reset_counter ();
- say count ();
- say count ();
1 2 3 1 2Now both functions can access the $counter variable, but still nothing outside the enclosing block can access it.
Static arrays and hashesAs 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:
- use strict ;
- use warnings ;
- use 5.010 ;
- sub fib {
- state @y ;
- @y = ( 1 , 1 ) if not @y ; # workaround initialization
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
- say fib ();
Alternatively we could use the "old-style" static variable with the enclosing block.
Here is the example generating the Fibonacci series:
- use strict ;
- use warnings ;
- use 5.010 ;
- {
- my @y = ( 1 , 1 );
- sub fib {
- push @y , $y [ 0 ]+ $y [ 1 ];
- return shift @y ;
- }
- }
- say fib ();
- say fib ();
- say fib ();
- say fib ();
![]() |
![]() |
![]() |
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)
![]() |
![]() |
![]() |
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.plBut 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.plLook 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 12345for readline support use rlwrap (you can use on
perl -d
too):$ rlwrap nc -v -l localhost -p 12345And start the test on another terminal (say terminal 2):
$ PERLDB_OPTS="RemotePort=localhost:12345" perl -d testInput/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:
1Note the sentence if you want output on debug terminal
select $DB::OUTIf you are vim user, install this plugin: dbg.vim which provides basic support for perl
![]() |
![]() |
![]() |
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 starts by displaying the next line to be executed: usually the first line in your program
- Debugger commands are mostly single letters, possibly with parameters. The command will be actioned as soon as you press Enter
- You should concentrate on commands
s
andn
to step through the program. If the next statement is a subroutine (or method) call thens
will step into the subroutine whilen
will step over the call. Otherwises
andn
behave identicallyBe careful using
s
when a single line of code contains multiple subroutine calls. You may not be stepping into the subroutine that you expectYou can't step into a built-in function, or a subroutine not written in Perl
Once you have executed a statement there is no going back. You must restart the program to try something different
- You can execute a line of Perl code just by typing it in and pressing Enter . the code will be executed in the context of the current statement
You can examine or modify any variable this way
- The
p
command is identical top $var
orp @arr
will be the same as if you had typedp $var
orp @arr
- You can use
x
to dump an expression in list context. The output consists of numbered lines showing each element of the list- The commands dot
.
, hyphen-
andv
are useful for looking at the source code..
and-
will display the current and previous source line respectively.v
will display a window around the current source line- To rapidly return to a specific line of code you can set a breakpoint and continue execution until that line using the
c
command. For examplec 13
Enter will execute all code until line 13 and then stopBreakpoints defined using
c
are temporary , so if you want to continue to the same line again (in a loop) then you have to enterc 13
Enter again
c
without any parameters will run the rest of the program until it exits or until a permanent breakpoint, defined usingb
, is reached- You can specify breakpoints with more complex conditions using the
b
command. They can be deleted only with the correspondingB
command, orB *
which will clear all breakpointsh
shows a list of the commands available, andh *command*
, likeh c
, will show you detailed help on a single command- Finally,
q
will end the debug session and terminate the programThe 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 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 0Now 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 errorand 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 STDERRwill 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 @mobyou 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:
- 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.- Otherwise, write 42 bytes to file descriptor 2
- 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 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 | 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:
- while ( my ( $key , $value ) = each %hash ) {
- print $key , "\n" ;
- delete $hash { $key } ; # This is safe
- }
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:
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.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:
![]() |
![]() |
![]() |
Jan 17, 2019 | stackoverflow.com
The second hit on "open url" at search.cpan brings