Re: Functions in Perl
by eyepopslikeamosquito (Archbishop) on May 23, 2004 at 02:14 UTC
|
Just a few general style comments. First, get into the habit of starting your programs with:
use strict;
at least until you understand when not to use it. I have not seen Lemay's book, but I trust it has a good explanation of use strict -- if not, discard it immediately. Second, drop the awful Perl-4 style:
&initarg;
function calling syntax and use the modern style:
initarg();
Third, lexicals are good. So replace:
foreach $i (@_) {
with:
foreach my $i (@_) {
Again, I trust Lemay describes why lexicals should generally be preferred to globals.
Like the others, I recommend switching to
learning perl. See
merlyn's blog entry for an interesting example of a Perl beginner learning Perl in public from merlyn's excellent introductory work.
| [reply] [d/l] [select] |
|
|
Interesting. Thanks! This is all good stuff! And I respect what merlyn has to say. Tremendously so! But don't particularly agree with that blog entry you pointed me to.
But again, I value your input.
| [reply] |
|
|
| [reply] |
Re: Functions in Perl
by rjray (Chaplain) on May 23, 2004 at 00:22 UTC
|
In the general sense, yes, your solution to the exercise is correct and functional. Many would suggest various tweaks and adjustments for the sake of clarity and/or efficiency, but overall it's good, and as a beginner you seem to be on a good track.
However, I would recommend moving to Learning Perl sooner rather than later. I have nothing against Laura Lemay, but most of the "Learn * in 21 Days" books focus too little on understanding the core topic itself, and leave the reader with limited ability to adapt and improvise.
--rjray
| [reply] |
|
|
Thanks man! I fully plan on reading that book! Everyone's been recommending it to me everywhere I turn! I generally trust O'Reilly's offerings to begin with. But I figure, it can't exactly hurt to finish the book I'm already half way through! Also generally speaking I tend to like to get my feet wet with a Sams 21 Days book and reinforce what I learned through more credible resources. That's how I did it with C++ at any rate, and I had some success there. So I decided that I am going to follow that formula again with Perl.
Also, I
I've found that writers inevitably see the same things in different ways. Obviously, one can never duplicate the exact experience or point of view of another human being! And I find that reading the exact same topic matter, covered from inevitably differing perspectives, has been immeasurably advantageous as a learning strategy.
| [reply] |
Re: Functions in Perl
by TomDLux (Vicar) on May 23, 2004 at 04:20 UTC
|
Modern practice is to make variables as local as possible. Creating a routine to initialize global variables is totally contrary to modern practice. As much as possible, functions/routines should only manipulate data and variables they recieve as arguments. As well, initializing an array to an empty array is pointless, as is initializing a strting to an empty string, or an integer to zero ... they are all created witht he value undef, which in many situations has the effect you assign explicitly. Admittedly, in certain odd situations, it becomes essential to assign a value to avoid pointless warning messages, but assigning routine intial values is a C practice, made obsolete by C++, Java and Perl.
As far as your printarg is concerned, it looks fine to me. However (You knew there was a however coming, didn't you?) the instructions only say to number the args, no comment about starting at zero or one or 17425. I would use that to my advantage to use the automatic numbering system of an array:
for my $idx ( 0..$#_ ) { # $#_ is index of last element,
# scalar @_ is number of elements
print "$idx $_[$idx]\n";
# or to start numbering at one
print $idx+1 . " $_[$idx]\n"
}
I was quick to learn $#array, took me a lot longer to learn 'scalar @array .... both are useful.
</code>
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] [d/l] |
Re: Functions in Perl
by Fletch (Bishop) on May 23, 2004 at 01:15 UTC
|
Unless you specifically need to format numbers to a particular number of decimal places or do zero-filling, using printf rather than just print (or even just interpolating into a double quoted string for that matter) is unnecessary (and makes you look like a C programmer :). You also will add the end token "stop" to your list. Consider using the more idiomatic while( <STDIN> ) { chomp; last if /^stop$/i; ... } instead.
You also might want to take a look at perltidy for a bit more idiomatic (and consistent) indentation. Not that this is python, but you're all over there with four, three, and zero spaces.
| [reply] [d/l] [select] |
Re: Functions in Perl
by Cody Pendant (Prior) on May 23, 2004 at 05:57 UTC
|
I just wanted to post that I believe you've interpreted the author's request incorrectly, or rather you've done way too much work!
The way I interpret it, she just wants you to write a sub such that, given subRoutine('foo','bar','baz','quux') it prints out
1 foo
2 bar
3 baz
4 quux
($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
=~y~b-v~a-z~s; print
| [reply] [d/l] [select] |
|
|
sub args { print "$_\n" for @_ }
args( qw( Perl is fun ) );
| [reply] [d/l] |
Re: Functions in Perl
by eric256 (Parson) on May 23, 2004 at 05:43 UTC
|
This incorporates a bit from the others and a bit of my own. :) Normaly I would shove the prompt into a sub of its own and use it as the condition for the while loop, but here i went with the simpler way! I came from C too although I started with ++ so I had streams for input output instead of printf.
use strict;
use warnings;
my @phrases = ();
my $i = 1;
print "Please enter phrase number " . $i++ . " (or 'stop'): ";
while (<STDIN>) {
chomp;
last if /^stop$/; #only if they put just the word stop
print "Please enter phrase number " . $i++ . " (or 'stop'): ";
push @phrases, $_;
}
printphrases(@phrases);
sub printphrases {
my $i = 1;
print $i++ . ") $_\n" foreach @_;
}
__DATA__
C:\test>perl input.pl
Please enter phrase number 1 (or 'stop'): hello world
Please enter phrase number 2 (or 'stop'): this is fun
Please enter phrase number 3 (or 'stop'): cool
Please enter phrase number 4 (or 'stop'): dude!
Please enter phrase number 5 (or 'stop'): stop
1) hello world
2) this is fun
3) cool
4) dude!
| [reply] [d/l] |
Re: Functions in Perl
by dash2 (Hermit) on May 23, 2004 at 22:02 UTC
|
One advantage (and sometimes, drawback) of Perl is that you can do things fast.
sub showargs{ print map {"$_ $_[$_]\n"} 0..$#_}
Doing things fast often leads to code that other people can't read. So don't assume this is good practice. But it's fun, and for a throwaway script it's acceptable.
An explanation:
map {code} @array runs code on every element of an array, just like a foreach loop. Inside the code block, each element of the array is aliased to $_.
0..$#array creates a list going from 0, to the index of the last element in @array. So 0..$#_ goes from 0 to the last element in @_, which is your array of arguments.
Finally, "$_ $_[$_]" prints first the aliased element, then the corresponding member of @_.
I'm sure some other monks can get this faster (and more obscure....)
| A massive flamewar beneath your chosen depth has not been shown here |
|
| [reply] [d/l] [select] |
Re: Functions in Perl
by Gunth (Scribe) on May 23, 2004 at 14:01 UTC
|
Also, an example like this is very suitable for an Object Oriented application. For example:
#!/usr/bin/perl
use strict;
use warnings;
my $example = Example->new;
$example->print(
map { chomp $_;
$_;
} <STDIN>
);
$example->print('That\'s all!');
sub Example::new {
my ($class, $start_num) = @_;
bless \$start_num, $class;
}
sub Example::print {
my $self = shift;
print ++$$self, ": $_\n" for @_;
}
| [reply] [d/l] |
|
|
Yikes! OOP is overkill here. This is all you need:
sub printargs {
my $i = 1;
printf "%d %s\n", $i++, $_
foreach @_;
}
| [reply] [d/l] |
|
|
That doesn't do what Gunth's OO code does. His code makes an object that holds the counter that keeps increasing for every call to &print. So the second time it continues where it stopped the first time. Your code has the equivalent result of throwing away the object after each use, i.e. Example::->new->(...).
My closure example below shows the equivalent of the OO example.
ihb
| [reply] [d/l] [select] |
|
|
my $printer = do {
my $c;
sub {
print ++$c, ": $_\n" for @_;
}
};
$printer->(@stuff_to_print);
$printer->(@more);
ihb | [reply] [d/l] [select] |
Re: Functions in Perl
by chanio (Priest) on May 24, 2004 at 01:59 UTC
|
| [reply] |