What is the Perlish way to iterate from item n to the end of an array? - perl

The problem is that I have n command-line arguments. There are always going to be at least 2, however the maximum number is unbounded. The first argument specifies a mode of operation and the second is a file to process. The 3rd through nth are the things to do to the file (which might be none, since the user might just want to clean the file, which is done if you just pass it 2 arguments).
I'm looking at the methods available to me in Perl for working with arrays, but I'm not sure what the "Perlish" way of iterating from item 3 to the end of my array is.
Some options that I've seen:
Pop from the end of the array until I find an element that does not begin with "-" (since the file path does not begin with a "-", although I suppose it could, which might cause problems).
Shift the array twice to remove the first two elements. Whatever I'm left with I can just iterate over, if its size is at least 1.
I like the second option, but I don't know if it's Perlish. And since I'm trying to learn Perl, I might as well learn the right way to do things in Perl.

Aside from using Getopt module as Sinan wrote, I would probably go with:
my ( $operation, $file, #things ) = #ARGV;
And then you can:
for my $thing_to_do ( #things ) {
...
}

IMHO, the Perlish way of accomplishing what you need would be to use one of the Getopt modules on CPAN.
If you still want to do it by hand, I would go for the second option (this is similar to how we handle the first argument of a method call):
die "Must provide filename and operation\n" unless #ARGV >= 2;
my $op = shift #ARGV;
my $file = shift #ARGV;
if ( #ARGV ) {
# handle the other arguments;
}

I would highly recommend using Getopt::Long for parsing command line arguments. It's a standard module, it works awesome, and makes exactly what you're trying to do a breeze.
use strict;
use warnings;
use Getopt::Long;
my $first_option = undef;
my $second_option = undef;
GetOptions ('first-option=s' => \$first_option,
'second-option=s' => \$second_option);
die "Didn't pass in first-option, must be xxxyyyzzz."
if ! defined $first_option;
die "Didn't pass in second-option, must be aaabbbccc."
if ! defined $second_option;
foreach my $arg (#ARGV) {
...
}
This lets you have a long option name, and automatically fills in the information into variables for you, and allows you to test it. It even lets you add extra commands later, without having to do any extra parsing of the arguments, like adding a 'version' or a 'help' option:
# adding these to the above example...
my $VERSION = '1.000';
sub print_help { ... }
# ...and replacing the previous GetOptions with this...
GetOptions ('first-option=s' => \$first_option,
'second-option=s' => \$second_option)
'version' => sub { print "Running version $VERSION"; exit 1 },
'help' => sub { print_help(); exit 2 } );
Then, you can invoke it on the command line using -, --, the first letter, or the entire option, and GetOptions figures it all out for you. It makes your program more robust and easier to figure out; it's more "guessable" you could say. The best part is you never have to change your code that processes #ARGV, because GetOptions will take care of all that setup for you.

The most standard way of doing things in Perl is through CPAN.
So my first choice would be Getopt::Long. There is also a tutorial on DevShed: Processing Command Line Options with Perl

You can use a slice to extract the 2nd. to last items, for example:
[dsm#localhost:~]$ perl -le 'print join ", ", #ARGV[2..$#ARGV];' 1 2 3 4 5 6 7 8 9 10 00
3, 4, 5, 6, 7, 8, 9, 10, 00
[dsm#localhost:~]$
however, you should probably be using shift (or even better, GetOpt::Long)

deepesz answer is one good way to go.
There is also nothing wrong with your second option:
my $op = shift; # implicit shift from #ARGV
my $file = shift;
my #things = #ARGV;
# iterate over #things;
You could also skip copying #ARGV into #things and work directly on it. However, unless the script is very short, very simple, and unlikely to grow more complex over time, I would avoid taking too many short cuts.
Whether you choose deepesz' approach or this one is largely a matter of taste.
Deciding which is better is really a matter of philosophy. The crux of the issue is whether you should modify globals like #ARGV. Some would say it is no big deal as long as it is done in a highly visible way. Others would argue in favor of leaving #ARGV untouched.
Pay no attention to anyone arguing in favor of one option or the other due to speed or memory issues. The #ARGV array is limited by most shells to a very small size and thus no significant optimization is available by using one method over the other.
Getopt::Long, as has been mentioned is an excellent choice, too.

Do have a look at MooseX::Getopt because it may whet your appetite for even more things Moosey!.
Example of MooseX::Getopt:
# getopt.pl
{
package MyOptions;
use Moose;
with 'MooseX::Getopt';
has oper => ( is => 'rw', isa => 'Int', documentation => 'op doc stuff' );
has file => ( is => 'rw', isa => 'Str', documentation => 'about file' );
has things => ( is => 'rw', isa => 'ArrayRef', default => sub {[]} );
no Moose;
}
my $app = MyOptions->new_with_options;
for my $thing (#{ $app->things }) {
print $app->file, " : ", $thing, "\n";
}
# => file.txt : item1
# => file.txt : item2
# => file.txt : item3
Will produce the above when run like so:
perl getopt.pl --oper 1 --file file.txt --things item1 --things item2 --things item3
These Moose types are checked... ./getopt --oper "not a number" produces:
Value "not a number" invalid for option oper (number expected)
And for free you always get a usage list ;-)
usage: getopt.pl [long options...]
--file bit about file
--oper op doc stuff
--things
/I3az/

For the more general case with any array:
for(my $i=2; $i<#array; $i++) {
print "$array[$i]\n";
}
That loops through the array, starting with the third element (index 2). Obviously, the specific example you specifiy, depesz's answer is the most straightforward and best.

Related

Use of uninitialized value $_ in hash element

This is regarding a warning message I received when running a Perl script.
I understand why I'm receiving this warning: probably because $element is undefined when being called but I don't see it.
for ( my $element->{$_}; #previous_company_names; ) {
map { $element => $previous_company_names->{$_} }
0 .. $previous_company_names;
The result is this message
Use of uninitialized value $_ in hash element
First and foremost - for a new programmer, absolutely the most important thing you must do, is use strict; and use warnings;. You've got my in there, which suggests you might be, but it pays to re-iterate it.
$_ is a special variable, called the implicit variable. It doesn't really make sense to use it in the way you're doing like that, in a for loop. Take a look at perlvar for some more detail.
Indeed, I'd suggest steering clear of map entirely until you really grok it, because it's a good way to confuse yourself.
With a for (or foreach) loop you can either:
for my $thing ( #list_of_things ) {
print $thing;
}
Or you can do:
for ( #list_of_things ) {
print $_;
}
$_ is set implicitly by each iteration of the second loop, which can be quite useful because lots of things default to using it.
E.g.
for ( #list_of_things ) {
chomp;
s/ /_/g;
print;
}
When it comes to map - map is a clever little function, that lets you evaluate a code block for each element in a list. Personally - I still get confused by it, and tend to stick with for or foreach loops instead, most of the time.
But what you're doing with it, isn't really going to work - map makes a hash.
So something like:
use Data::Dumper;
my %things = map { $_ => 1 } 1..5;
print Dumper \%things;
This creates the hash 'things':
$VAR1 = {
'1' => 1,
'3' => 1,
'5' => 1,
'4' => 1,
'2' => 1
};
Again, $_ is used inside, because it's the magic variable - it's set to 'whatever was in the second bit' (e.g 1,2,3,4,5) each loop, and then the block is evaluated.
So your map expression doesn't really make a lot of sense, because you don't have $element defined... and even if you did, you'd repeatedly overwrite it.
I would also note - $previous_company_names would need to be numeric, and is in NO way related to #previous_company_names. You might be meaning to use $#previous_company_names which is the last element index.

Perl: How to break on write-to-variable in Eclipse

I have a script that is writing entries into a hash. However, at a certain point entries exist in the hash that I think should not. So, obviously I've cocked it up somewhere, but there is only one place where I think I add elements in to the hash and I've tested that to make sure that these "rogue" elements aren't being added at this location.
What I would like to do is break on a write to the hash, something like this, but in a "global" kinda way because I don't know where this stray write is in the code - I can't see it...
So what are my options? Can I set a watch point in the EPIC debugger and if so how? (I've had a play but can;t find anything relevant).
Or could I perhaps create a extended hash that can intercept writes somehow?
Any ideas on an "easy" debugging method. Otherwise I think I'll be back to brute force debug :S Thanks in davance...
Not an EPIC-specific answer, but check out Tie::Watch. You can setup a variable (like a hash) to be watched, and your program can output something every time the variable is updated.
updated: Tie::Trace does pretty much the same thing, with a simpler interface.
Here is a DIY-version of mobs answer: Make that hash a tied hash to a class that outputs a stack trace on every write access:
package MyHash {
use Tie::Hash;
use parent -norequire, "Tie::StdHash";
use Carp "cluck";
sub STORE {
my ($self, $k, $v) = #_;
cluck "hash write to $self: $k => $v";
$self->SUPER::STORE($k => $v);
}
}
tie my %hash => "MyHash";
$hash{foo} = 42;
print "$hash{foo}\n";
Output:
hash write to MyHash=HASH(0x91be87c): foo => 42 at -e line 1.
MyHash::STORE('MyHash=HASH(0x91be87c)', 'foo', 42) called at -e line 1
42
use Hash::Util qw(
lock_keys unlock_keys
lock_hash unlock_hash
);
my %hash = (foo => 42, bar => 23);
# no keys change
lock_keys(%hash);
# no keys/values change
lock_hash(%hash);

Not able to restrict the number of arguments for an option with GetOptions in Getopt::Long

My program is as follows:
use strict;
use warnings;
use Getopt::Long;
my #letters;
my #words;
GetOptions(
"letters=s{2}" => \#letters,
"words=s{,}" => \#words
);
print "Letters: " . join(", ", #letters) . "\n";
print "Words: " . join(", ", #words) . "\n";
When I run this program I get the output as follows:
perl getopts.pl --letters a --words he she it
Letters: a, --words
Words:
--words is read as part of --letters arguments itself. I expect GetOptions to throw error message in this scenario. How to get this done.
Change:
"letters=s{2}" => \#letters,
to:
"letters=s{1,2}" => \#letters,
...which allows 1-to-2 letters as the argument.
A quantifier of '{2}' means "exactly two". So, it's even ignoring the second argument afterwards is a switch.
The GetOpt::Long text that you probably took this from:
GetOptions( 'coordinates=f{2}' => \#coor, 'rgbcolor=i{3}' => \#color );
Are specific conditions for which pairs and triads make sense. You want an x and a y coordinate, or you want a value for each part of an RGB specification. Just the way that you would expect 'cmykcolor={4}'.
If you want at least one, up to the next switch, you can specify '{1,}' as your quantifier, and if you want "at most two", then '{1,2}' makes sense. Interestingly enough, the behavior of '{,2}' is exactly the same as '{1,2}'. It seems that as long as you specify a quantifier, it will suck up one more argument, regardless of whether or not the next argument is a switch.
So the quantifiers in Getopt::Long may look the same as regex, but they mean different things.

How could you retrieve a method's POD from inside a REPL or debugger?

I would like to be able to see the documentation of a method/function when using it inside REPL or debuger.
Is there any module that allow you to see the documentation of a function when using REPL or a debuger?.
Obviously if that module exist it would ask you to have your POD and code with a parseable structure in order to extract the docs. That is not a problem because I have all my code documented and I can adapt to whatever is needed. Currently I have all my methods with a preceding POD with a =head2 method_name and the typical lines for name, usage, example, args, return, exeptions etc
The typical example is when you are in the debuger (or REPL) and you want to use a function and you don't remember the order of arguments or their types, or the type of the return element or you want a hint for the usage.
I would like to have something like get_pod($moudle_bar, $method_foo), or even better being able to put a get_pod in a base module and being able to say $bar->get_pod('foo'). I know that this is not trivial and has a lot of corner cases. This is the reason that I am asking about a method-POD extractor module.
I want to show the output inside the REPL or debuger so any pointer to an anchored html-pod in a browser is not convenient for me.
It could be that there is something much more simple and I am obfuscated.
My first brute force and expensive approach:
> $self = new MyModule
> m $self # to see the available methods for double check the spelling
> # method wanted '_connect_db'
> $cmd = 'perldoc -t ' . ref($self)
> x qx{$cmd}=~/(_connect_db.*?)\n\n/msg
0 '_connect_db
Title : _connect_db
Usage :
Function: create a database conection and return the handler
Example : $dbh = $self->_connect_db($user, $pass, $db_name) # host is FPrefect by default
Returns : [0] DBI $dbh object
Args :
[0] $user,
[1] $pass,
[2] $db_name,
[3] $host,
[4] $db_brand # mysql, sqlite
[5] $mode = (ro, rw) # not used now. in the future it would use this for read the user and password'
Obviously this works because I know that I don't have any empty lines in my method description PODs so I use .*?)\n\n in the regex to capture the rest of the method POD.
Do someone have any good suggestion or advice for this task?
UPDATE:
Following snoopy suggestions I have taken a look at Pod::Coverage source code and I found that Pod::Coverage::Extractor (a package inside the file for Pod::Coverage) has the method command that look for Pods Item or head elements and extract them. I will take a look how to retrieve this items.
# package Pod::Coverage::Extractor
#extract subnames from a pod stream
sub command {
my $self = shift;
my ( $command, $text, $line_num ) = #_;
if ( $command eq 'item' || $command =~ /^head(?:2|3|4)/ ) {
# take a closer look
my #pods = ( $text =~ /\s*([^\s\|,\/]+)/g );
$self->{recent} = [];
foreach my $pod (#pods) {
print "Considering: '$pod'\n" if debug;
# it's dressed up like a method cal
$pod =~ /-E<\s*gt\s*>(.*)/ and $pod = $1;
$pod =~ /->(.*)/ and $pod = $1;
# it's used as a (bare) fully qualified name
$pod =~ /\w+(?:::\w+)*::(\w+)/ and $pod = $1;
# it's wrapped in a pod style B<>
$pod =~ s/[A-Z]<//g;
$pod =~ s/>//g;
# has arguments, or a semicolon
$pod =~ /(\w+)\s*[;\(]/ and $pod = $1;
print "Adding: '$pod'\n" if debug;
push #{ $self->{ $self->{nonwhitespace}
? "recent"
: "identifiers" } }, $pod;
}
}
UPDATE 2
Another place from where to take info is pdoc. This script generates html for browsing APIs and I use it in Ensembl and BioPerl. I am sure I will learn something reading the source code.
I also could find any single CPAN module that does exactly want you want.
I wonder if you could somehow combine Pod::Coverage and Pod::Select.
Pod::Coverage lets you get at the symbols as below:
snoopy#deb6:~$ perl -de0
DB<1> use Pod::Coverage
DB<2> our $pc = Pod::Coverage->new(package => 'Mouse');
DB<3> $pc->coverage;
DB<4> use Data::Dumper
DB<5> p Dumper $pc->{symbols}
$VAR1 = {
'around' => 1,
'init_meta' => 0,
'super' => 0,
'has' => 1,
'after' => 1,
'augment' => 0,
'inner' => 0,
'override' => 0,
'with' => 0,
'extends' => 1,
'before' => 1
};
Maybe Pod::Select (or Similar) could then be used to extract the relevant sections?
EDIT or maybe subclass/modify Pod::Coverage to gather body text along with the symbols.
PDL's interactive shell (perldl) lets you read PDL's docs with the ? and ?? commands, perhaps something like that can be done for REPL.

What are some elegant features or uses of Perl?

What? Perl Beautiful? Elegant? He must be joking!
It's true, there's some ugly Perl out there. And by some, I mean lots. We've all seen it.
Well duh, it's symbol soup. Isn't it?
Yes there are symbols. Just like 'math' has 'symbols'. It's just that we programmers are more familiar with the standard mathematical symbols. We grew to accept the symbols from our mother languages, whether that be ASM, C, or Pascal. Perl just decided to have a few more.
Well, I think we should get rid of all the unnecessary symbols. Makes the code look better.
The language for doing so already exists. It's called Lisp. (and soon, perl 6.)
Okay, smart guy. Truth is, I can already invent my own symbols. They're called functions and methods. Besides, we don't want to reinvent APL.
Oh, fake alter ego, you are so funny! It's really true, Perl can be quite beautiful. It can be quite ugly, as well. With Perl, TIMTOWTDI.
So, what are your favorite elegant bits of Perl code?
Perl facilitates the use of lists/hashes to implement named parameters, which I consider very elegant and a tremendous aid to self-documenting code.
my $result = $obj->method(
flux_capacitance => 23,
general_state => 'confusion',
attitude_flags => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL,
);
My favourite pieces of elegant Perl code aren't necessarily elegant at all. They're meta-elegant, and allow you to get rid of all those bad habits that many Perl developers have slipped into. It would take me hours or days to show them all in the detail they deserve, but as a short list they include:
autobox, which turns Perl's primitives into first-class objects.
autodie, which causes built-ins to throw exceptions on failure (removing most needs for the or die... construct). See also my autodie blog and video).
Moose, which provide an elegant, extensible, and correct way of writing classes in Perl.
MooseX::Declare, which provides syntaxic aweseomeness when using Moose.
Perl::Critic, your personal, automatic, extensible and knowledgeable code reviewer. See also this Perl-tip.
Devel::NYTProf, which provides me the most detailed and usable profiling information I've seen in any programming language. See also Tim Bunce's Blog.
PAR, the Perl Archiver, for bundling distributions and even turning whole programs into stand-alone executable files. See also this Perl-tip.
Perl 5.10, which provides some stunning regexp improvements, smart-match, the switch statement, defined-or, and state variables.
Padre, the only Perl editor that integrates the best bits of the above, is cross-platform, and is completely free and open source.
If you're too lazy to follow links, I recently did a talk at Linux.conf.au about most of the above. If you missed it, there's a video of it on-line (ogg theora). If you're too lazy to watch videos, I'm doing a greatly expanded version of the talk as a tutorial at OSCON this year (entitled doing Perl right).
All the best,
Paul
I'm surprised no one mentioned the Schwartzian Transform.
my #sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, expensive_func($_) ] }
#elements;
And in the absence of a slurp operator,
my $file = do { local $/; readline $fh };
Have a list of files the user wants your program to process? Don't want to accidentally process a program, folder, or nonexistent file? Try this:
#files = grep { -T } #files;
And, like magic, you've weeded out all the inappropriate entries. Don't want to ignore them silently? Add this line before the last one:
warn "Not a file: $_" foreach grep { !-T } #files;
Prints a nice warning message for every file that it can't process to standard error. The same thing without using grep would look like this:
my #good;
foreach(#files) {
if(-T) {
push #good, $_;
} else {
warn "Not a file: $_";
}
}
grep (and map) can be used to make code shorter while still keeping it very readable.
The "or die" construct:
open my $fh, "<", $filename
or die "could not open $filename: $!";
The use of qr// to create grammars:
#!/usr/local/ActivePerl-5.10/bin/perl
use strict;
use warnings;
use feature ':5.10';
my $non_zero = qr{[1-9]};
my $zero = qr{0};
my $decimal = qr{[.]};
my $digit = qr{$non_zero+ | $zero}x;
my $non_zero_natural = qr{$non_zero+ $digit*}x;
my $natural = qr{$non_zero_natural | $zero}x;
my $integer = qr{-? $non_zero_natural | $zero}x;
my $real = qr{$integer (?: $decimal $digit)?}x;
my %number_types = (
natural => qr/^$natural$/,
integer => qr/^$integer$/,
real => qr/^$real$/
);
for my $n (0, 3.14, -5, 300, "4ever", "-0", "1.2.3") {
my #types = grep { $n =~ $number_types{$_} } keys %number_types;
if (#types) {
say "$n is of type", #types == 1 ? " ": "s ", "#types";
} else {
say "$n is not a number";
}
}
Anonymous subroutines used to factor out duplicate code:
my $body = sub {
#some amount of work
};
$body->();
$body->() while $continue;
instead of
#some amount of work
while ($continue) {
#some amount of work again
}
Hash based dispatch tables:
my %dispatch = (
foo => \&foo,
bar => \&bar,
baz => \&baz
);
while (my $name = iterator()) {
die "$name not implemented" unless exists $dispatch{$name};
$dispatch{$name}->();
}
instead of
while (my $name = iterator()) {
if ($name eq "foo") {
foo();
} elsif ($name eq "bar") {
bar();
} elsif ($name eq "baz") {
baz();
} else {
die "$name not implemented";
}
}
Three-line classes with constructors, getter/setters and type validation:
{
package Point;
use Moose;
has ['x', 'y'] => (isa => 'Num', is => 'rw');
}
package main;
my $point = Point->new( x => '8', y => '9' );
$point->x(25);
A favorite example of mine is Perl's implementation of a factorial calculator. In Perl 5, it looks like so:
use List::Util qw/reduce/;
sub factorial {
reduce { $a * $b } 1 .. $_[0];
}
This returns false if the number is <= 1 or a string and a number if a number is passed in (rounding down if a fraction).
And looking forward to Perl 6, it looks like this:
sub factorial {
[*] 1..$^x
}
And also ( from the blog in the link above ) you can even implement this as an operator:
sub postfix:<!>(Int $x) {
[*] 1..($x || 1)
}
and then use it in your code like so:
my $fact5 = 5!;
If you have a comma separated list of flags, and want a lookup table for them, all you have to do is:
my %lookup = map { $_ => 1 } split /,/, $flags;
Now you can simply test for which flags you need like so:
if ( $lookup{FLAG} ) {
print "Ayup, got that flag!";
}
I am surprised no one has mentioned this. It's a masterpiece in my opinion:
#!/usr/bin/perl
$==$';
$;||$.| $|;$_
='*$ ( ^#(%_+&~~;# ~~/.~~
;_);;.);;#) ;~~~~;_,.~~,.* +,./|~
~;_);#-, .;.); ~ ~,./##-__);#-);~~,.*+,.
/|);;;~~#-~~~~;.~~,. /.);;.,./#~~#-;.;#~~#-;;
;;,.*+,./.);;#;./#,./ |~~~~;#-(#-__#-__&$#%^';$__
='`'&'&';$___="````" |"$[`$["|'`%",';$~=("$___$__-$[``$__"|
"$___"| ("$___$__-$[.%")).("'`"|"'$["|"'#").
'/.*?&([^&]*)&.*/$'.++$=.("/``"|"/$[`"|"/#'").(";`/[\\`\\`$__]//`;"
|";$[/[\\$[\\`$__]//`;"|";#/[\\\$\\.$__]//'").'#:=("#-","/.",
"~~",";#",";;",";.",",.",");","()","*+","__","-(","/#",".%","/|",
";_");#:{#:}=$%..$#:;'.('`'|"$["|'#')."/(..)(..)/".("```"|"``$["|
'#("').'(($:{$'.$=.'}<<'.(++$=+$=).')|($:{$'.$=.'}))/'.("```;"|
"``$[;"|"%'#;").("````'$__"|"%$[``"|"%&!,").${$[};`$~$__>&$=`;$_=
'*$(^#(%_+&#-__~~;#~~#-;.;;,.(),./.,./|,.-();;#~~#-);;;,.;_~~#-,./.,
./#,./#~~#-);;;,.(),.;.~~#-,.,.,.;_,./#,.-();;#~~#-,.;_,./|~~#-,.
,.);););#-#-__~~;#~~#-,.,.,.;_);~~~~#-);;;,.(),.*+);;# ~~#-,
./|,.*+,.,.);;;);*+~~#-,.*+,.;;,.;.,./.~~#-,.,.,.;_) ;~~~
~#-,.;;,.;.,./#,./.);*+,.;.,.;;#-__~~;#~~#-,.;;,.* +);;
#);#-,./#,./.);*+~~#-~~.%~~.%~~#-;;__,. /.);;##- __#-
__ ~~;;);/#;#.%;#/.;#-(#-__~~;;;.;_ ;#.%~~~~ ;;()
,.;.,./#,. /#,.;_~~#- ););,.;_ );~~,./ #,.
;;;./#,./| ~~~~;#-(#- __,.,.,. ;_);~~~ ~#
-~~());; #);#-,./#, .*+);;; ~~#-~~
);~~);~~ *+~~#-);-( ~~#-#-_ _~~#-
~~#-);; #,./#,.;., .;.);# -~~#-;
#/.;#-( ~~#-#-__ ~~#-~~ #-);#
-);~~, .*+,./ |);;;~ ~#-~~
;;;.; _~~#-# -__);. %;#-(
#-__# -__~~;# ~~#-;; ;#,.
;_,.. %);#-,./#, .*+,
..%, .;.,./|) ;;;)
;;#~ ~#-,.*+,. ,.~~
#-); *+,.;_);;.~ ~););
~~,.; .~~#-);~~,.;., ./.,.;
;,.*+ ,./|,.); ~~#- );;;,.(
),.*+); ;#~~/|#-
__~~;#~~ $';$;;
I absolutely love Black Perl (link to version rewritten to compile under Perl 5). It compiles, but as far as I can tell it doesn't actually do anything.
That's what you get for a language written by a linguist from a pragmatic perspective rather than from a theoretical perspective.
Moving on from that, you can think about the Perl that people complain about as pidgin Perl (perfectly useful, but not expressive, and beware of trying to express anything complex in it), and the stuff that #pjf is talking about as "proper" Perl, the language of Shakespeare, Hemingway, Hume and so on. [edit: err, though easier to read than Hume and less dated than Shakespeare.] [re-edit and hopefully less alcoholic than Hemingway]
Adding to the love of map and grep, we can write a simple command-line parser.
my %opts = map { $_ => 1 } grep { /^-/ } #ARGV;
If we want, we can set each flag to it's index in #ARGV:
my %opts = map { $ARGV[$_] => $_ } grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV;
That way, if a flag has an argument, we can get the argument like this:
if( defined( $opts{-e} ) ) {
my $arg = $ARGV[ $opts{-e} ];
# do -e stuff for $arg
}
Of course, some people will cry that we're reinventing the wheel and we should use getopt or some variant thereof, but honestly, this was a fairly easy wheel to reinvent. Plus, I don't like getopt.
If you don't like how long some of those lines are, you can always use intermediate variables or just convenient line breaks (hey, Python fanatics? You hear that? We can put one line of code across two lines and it still works!) to make it look better:
my %opts = map { $ARGV[$_] => $_ }
grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV;
This file parsing mechanism is compact and easy to customize (skip blank lines, skip lines starting with X, etc..).
open(H_CONFIG, "< $file_name") or die("Error opening file: $file_name! ($!)");
while (<H_CONFIG>)
{
chomp; # remove the trailing newline
next if $_ =~ /^\s*$/; # skip lines that are blank
next if $_ =~ /^\s*#/; # skip lines starting with comments
# do something with the line
}
I use this type of construct in diverse build situations - where I need to either pre or post process payload files (S-records, etc..) or C-files or gather directory information for a 'smart build'.
My favourite elegant Perl feature is that it uses different operators for numerical values and string values.
my $string = 1 . 2;
my $number = "1" + "2";
my $unambiguous = 1 . "2";
Compare this to other dynamic languages such as JavaScript, where "+" is used for concatenation and addition.
var string = "1" + "2";
var number = 1 + 2;
var ambiguous = 1 + "2";
Or to dynamic languages such as Python and Ruby that require type coercion between strings and numberical values.
string = "1" + "2"
number = 1 + 2
throws_exception = 1 + "2"
In my opinion Perl gets this so right and the other languages get it so wrong.
Poorer typists like me who get cramps hitting the shift key too often and have an almost irrational fear of using a semicolon started writing our Perl code in python formatted files. :)
e.g.
>>> k = 5
>>> reduce(lambda i,j: i*j, range(1,k+1),1)
120
>>> k = 0
>>> reduce(lambda i,j: i*j, range(1,k+1),1)
1