Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Perl aesthetics: the good, the bad, the ugly.

by vladb (Vicar)
on May 01, 2002 at 12:44 UTC ( #163251=perlmeditation: print w/ replies, xml ) Need Help??

Don't worry, this post is not an Apocalypse, however, it may refer to certain passages from St. Larry Wall's writings therein.

As Larry Wall himself puts it:

"Multiple syntaxes sound like an evil thing, but they're really necessary for the evolution of the language. To some extent we already have a multi-syntax model in Perl 5"

Perl is particularly insensitive to individual programmer's coding styles and syntax, so long of course it 'compiles'. I believe this allows Perl to be regarded as a tool for expressing one's creativity and culture while still doing his/her job. This is unarguably a good thing. However, to some extent this rather liberal feature of perl is subject to common abuse if not approached with due diligence.

Poorly composed and formatted perl code most often serves as the prevailing deterrent for newcomers to this language. And this is certainly a bad thing, especially for Perl advocacy groups and individual perl evangelists alike. For one I know, my heart rejoices when I see an old friend of mine well versed in the manners of other languages (such as C/C++, for example) convert to and partake in the joy of breathing, writing, and thinking Perl.

A few days ago, I stumbled on an old article (dated back to 2001) which sheds a little more light on this very subject. The post is titled Perl: ugly and not suitable. Here's a startling quote from a follow up reply post:

"Perl's main drawback is that parts of it are irredeemably ugly, complicated, and must be used with caution and in stereotyped ways lest they bite (its argument-passing conventions for functions are a good example of all three)"

Being as much of a Perl devotee as I am, my first reaction would be to sharply disagree with this conjecture. On the other hand, however, there's always a grain of truth in every lie ;-). There are horrible ways of dealing with subroutine arguments as well as there are elegant ways. Most of it is described to some extent in these posts: To summarize, I tend to believe most of us would agree that dealing with subroutines (especially in a piece of code you inherited from another developer) that accept over four arguments is not the best experience one would prefer to go through. Here's an example:
sub create_index { my ($dbh, $index_name, $frontend, $backend, $scoring) = @_; . . . } . . . my $index = create_index($dbh, 'search_index', 'string', 'phrase', 1);
However, passing a hash structure where subroutine parameters are clearly expressed through hash key names is aesthetically clean and provides for a flexible way to manage subroutine arguments (adding new parameters or removing old ones). I regard this as a truly seamless way of dealing with subroutine arguments that is unmatched in any other programming languages such as C++, Java, Basic etc.
sub create_index { my %args = @_; # retrieve/use subroutine parameters from the # %args hash! . . . } . . . my $index = create_index( dbh => $dbh, index_name => 'search_index', frontend => 'string', backend => 'phrase' scoring => 1 );
Of course, there are some extreme rebels who would be opposed to the whole idea of using some 'ubiquitous' @_ variable to handle subroutine parameters. Well, and I'm not in here to argue with them - evidently, nothing could bring such a vial heart to repentance ;).

Do you have your stories of good, bad, or outright ugly Perl code? While trying to keep this post short, I would appreciate a continued discussion. Thanks for your attention ;-).

"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith

Comment on Perl aesthetics: the good, the bad, the ugly.
Select or Download Code
Re: Perl aesthetics: the good, the bad, the ugly.
by BUU (Prior) on May 01, 2002 at 13:12 UTC
    Sigils. "Best Thing Ever?" IMHO, yup! Even though sigils tend to enhance the 'noisyness' of a line, once you learn to read them, theyres no going back. Sigils do so much more to promote code legibility and understanding then practicly any other structure in the language. The ability to know instantly what data type something is, is invaluable. You could get into scalar references, but in general those are still understandable. You know that whatever is in $var is going to be a singular value, whatever it is, and you know if you see @$var that $var is supposed to be a refference to an array. Much cleaner then random pointers. Again, this is all IMHO of course, etc etc.
Re: Perl aesthetics: the good, the bad, the ugly.
by Molt (Chaplain) on May 01, 2002 at 13:15 UTC

    I'm glad you picked argument passing as your example, since the ugliest piece of bad Perl I've ever seen(Hey, two out of three ain't bad) is argument passing.

    I was beginning to maintain an out-of-house piece of Perl, and was happily reading through it sorting the small pile of wheat from the large pile of chaff when suddenly I hit a brick.

    The programmer had, I think, intended to get the kind of default arguments that hashes can easily provide.. but had tried to do it without any kind of hash. They also had odd argument ordering, with related arguments randomly places around the sequence so often the value you needed to default would be in the middle of the 'full' list. I think they were just adding new items to the end as they became required.

    I'm now in a new job, so I can't get this code to show you, but here's the essence of how it worked. I'm refusing to comment this, for those Initiates of Perl who can't work out how this works think yourselves lucky and go and reread the hash method.

    And yes, the 'use strict' and -w bits were added by me for my example. They didn't use these either, oddly enough.

    #!/usr/bin/perl -w use strict; DoStuff (1,2,3); DoStuff (1,3); DoStuff (2); sub DoStuff { my ($a, $b, $c) = (-1, -2, -3); if ($#_ == 2) { ($a, $b, $c) = @_; } elsif ($#_ == 1) { ($a, $c) = @_; } elsif ($#_ == 0) { ($b) = @_; }; print "A= $a\n"; print "B= $b\n"; print "C= $c\n"; }

    I'm thankful not to be in that job anymore.

    Other bits of wonder I've seen..

    • Regexps used for XML parsing which also rely on the positions of newlines. Good thing the same company wrote the program which generates the XML really.
    • A nice bug where someone was initialising hashes with '%hash = {}' instead of '%hash = ()' and then wondering why they were getting a nonsense result.
    • A recursive program that executed itself with backticks.
    • Form-driven CGIs which took parameters like "delete * from users where username='eric'", where the eric bit was template-driven as the form was output. The programmer couldn't see why this was a security hole as he knew what he'd printed.

    I love maintaining the code of people who don't really know Perl, it's ingenious some of the things they can get up to.

      ...but this is proof not of the ugliness of Perl, but of the ugliness of someone's mind.

      Where that person wrote:

      sub DoStuff { my ($a, $b, $c) = (-1, -2, -3); if ($#_ == 2) { ($a, $b, $c) = @_; } elsif ($#_ == 1) { ($a, $c) = @_; } elsif ($#_ == 0) { ($b) = @_; }; print "A= $a\n"; print "B= $b\n"; print "C= $c\n"; }

      We might instead write:

      sub DoStuff { my ($a, $b, $c) = @_; $a = defined $a ? $a : -1; $b = defined $b ? $b : -2; $c = defined $c ? $c : -3; print "A= $a\n"; print "B= $b\n"; print "C= $c\n"; }

      And while this lacks some elegance (for instance, I might want to create a loop that simply tests $_[0] and then shifts the top value into the next of my variables), I think it would be a simple improvement.

      The real point is that the language allows us to be ugly. Some of choose to do so.

      ---v

        Note that if there are 2 arguments, the original code set $a and $c, not $a and $b.

        -Mike

Re: Perl aesthetics: the good, the bad, the ugly.
by cjf (Parson) on May 01, 2002 at 13:17 UTC
    I believe this allows Perl to be regarded as a tool for expressing one's creativity

    That it is. While this flexibility is very nice most of the time, it does unfortunately also lead to things like Perl Poetry. (Hi to all the poetry fans out there =P)

    Perl's main drawback is that parts of it are irredeemably ugly, complicated, and must be used with caution

    You don't blame the brush if you can't paint do you? Yes, encounters with some poorly written code do occasionally turn people off Perl. However, to look at one piece of code, say that's ugly, and write off a language is rather naive. People who are serious about finding the best tool for their job will look a little closer and realize the benefits of such flexibility and how to use it to their advantage.

    Update: Also part of the quote you linked to...

    Because some limiting design decisions early in Perl's history could not be reversed, many of the more advanced features have a fragile, jerry-rigged feel about them.

    That I will agree with.

Re: Perl aesthetics: the good, the bad, the ugly.
by Maclir (Curate) on May 01, 2002 at 14:42 UTC
    Your comment:
    I believe this allows Perl to be regarded as a tool for expressing one's creativity and culture while still doing his/her job. This is unarguably a good thing.
    Hmmm. I am not sure I totally agree with you here. When managing a large development project, with 20 developers involved, the last thing I want to manage is individual programmers expressing their "creativity and culture" in strange ways. (I recall one programmer who would intersperse his code with latin comments.)

    Imagine that a year or two in the future, you are the sole maintenance programmer for a system developed by ten programmers all given full rein to their individual expressions of creativity and culture. All the more reason for enforcing a site standard in style and structure.

    Of course, in a well managed team, peer reviews and code walkthroughs should remove the most extreme cases of wierd individual style.

Re: Perl aesthetics: the good, the bad, the ugly.
by PotPieMan (Hermit) on May 01, 2002 at 14:48 UTC
    On fuction definition: I prefer specifying the parameters up front. In a way, the function is self-documenting if you force yourself to specify the parameters. Of course, you can document your %args hash, but chances are you'll forget. (In my experience, it's better to be skeptical about one's willingness to document.)

    Compare the following (which are directly from your writeup):

    ### Parameters explicitly listed sub createIndex { my ($dbh, $indexName, $frontend, $backend, $scoring) = @_; ... } ### Parameters passed in by hash, but no documentation sub createIndex { my %args = @_; ... }

    If I'm new to a project, or if I'm coming back to a project after a few months working on something else, the second version becomes more difficult to use/modify/understand - the method becomes less of a "black box", in my opinion.

    I'm going to be somewhat of a heretic here, and say that function definition in other languages, such as C, C++, and Java, looks better and is easier to understand. For example,

    public void createIndex(Connection conn, String indexName, String fron +tend, String backend, int scoring) { ... }

    For me, the only issue with this is flexibility. If you don't want one of the parameters (say, scoring), you have to overload createIndex with a second instance of the method. Done wrong, this could lead to code duplication. Done right, there is one "base" method that can handle all cases, meaning no code is duplicated. It's just not as flexible as the Perl version.

    A lot of my time recently has been spent considering how another programmer sees my code (another programmer was recently hired where previously I was the only one). We had to come up with certain rules for Perl programming, rules that we sort of took for granted in Java. This suggests, as you say, that Perl allows you to be more creative - but you have to weigh your creativity against your need to get the job done. I'm not saying that you can't have both - I program because I am creative. I've found that on the job, you have to be careful about how you program.

    Update: Fixed a typo.

    --PotPieMan

Re: Perl aesthetics: the good, the bad, the ugly.
by chromatic (Archbishop) on May 01, 2002 at 14:55 UTC
    The tradeoff: if you're running under strict and mistype a variable name, the compiler tells you. If you're running under strict, warnings, and taint mode and mistype a hash key, the compiler doesn't.

    That's why I try not to pass too many arguments -- it's a sign that the function is too complicated.

      This is why you always have a param checking sub that you turn off unless $ENV{DEBUG} or something is true. There's plenty of examples of this type if thing on CPAN.
        Do these check that all uses of the param hash use the right keys? What you describe sounds to me like a sub that's called when populating the hash from @_ -- that's a good idea, but it's still not strict enough. I've come across code that uses 'style' in one place and 'stytle' in others.

        Clamped, read-only, psuedo-, or tied-hashes can fix this, but they're probably rare in production code.

        I wouldn't mind this convenience occasionally...

Re: Perl aesthetics: the good, the bad, the ugly.
by Sifmole (Chaplain) on May 01, 2002 at 17:08 UTC
    "Perl's main drawback is that parts of it are irredeemably ugly, complicated, and must be used with caution and in stereotyped ways lest they bite (its argument-passing conventions for functions are a good example of all three)"

    I have seen so many variations of this statement and it still seems to say absolutely nothing to me about Perl. It seems to me that you could put almost any language at the front and find some aspect(s) of it that fit the description.

    As regards the arguement-passing convention, is it really so complicated? that much more so than say C's? And there is such an elegant way to use the parameter passing, the hash method; In most languages such a divergent solution from the standard wouldn't be possible.

    I started using an example of a string in C but decided it was long winded and didn't really add anything... It just made me happy I have Perl.

Re: Perl aesthetics: the good, the bad, the ugly.
by Ovid (Cardinal) on May 01, 2002 at 23:31 UTC

    Here's my horrible confession. We often hear that you can program Perl to resemble your favorite programming language/style. C-style for loops are the classic example:

    for ( my $i = 0; $i < @array; $i++ ) { ... }

    We're admonished to avoid that, if possible, due to classic "off by one" errors.

    my @array = qw/ zero one two three four /; for ( my $i = 0; $i < $#array; $i++ ) { print $array[$i],$/; }

    LISP programmers appreciating the aesthetics of the Schwartzian Transform is another example.

    Confession time: I used to be a COBOL programmer. Oh, I used strict, warnings, taint checking, and whatever else I thought was "good", but I had a bad habit of writing my subroutines "COBOL-style", with the exception of passing in the arguments.

    sub foo { my $arg = shift; foreach my $data ( @data ) { $bar[ $data ] += $arg; } }

    I know better now, but it took me a long time to see the error of my ways :(

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Perl aesthetics: the good, the bad, the ugly.
by BUU (Prior) on May 02, 2002 at 01:42 UTC
    I would like to submit as my entry:
    1 #!/usr/bin/perl 2 use Getopt::Std; 3 getopt('dV'); 4 $xferlog="./xferlog"; 5 $\ = "\n"; 6 $i=0; 7 open XFERLOG, $xferlog or die "Cant't find file $xferlog"; 8 9 foreach $line (<XFERLOG>) { 10 chomp($line); 11 if (( $line =~ /$opt_d/i) && ( $line !~ /_ o r/)) 12 { 13 ($Fld1,$Fld2,$Fld3,$Fld4,$Fld5,$Fld6,$Fld7,$Fld8, $Fld9,$Fld10,$Fld11,$Fld12,$Fld13,$Fld14,$Fld15) = spli +t(' ',$line); 14 $uplist[$i] = join ' ',$Fld6, $Fld8, $Fld9, $Fld14, +$Fld15; 15 $time[$i]=$Fld6; $size[$i]=$Fld8; $file[$i]=$Fld9; $user[$i]=$Fld14; $group[$i]=$Fld15; 16 $username= join '@', $user[$i], $group[$i]; 17 push @{$table{$username}}, $uplist[$i]; 18 $i++; 19 } 20 } 21 close XFERLOG; 22 23 undef %saw; 24 # @newuser = grep(!$saw{$_}++, @user); 25 $j=0; 26 foreach $username ( sort keys %table ) 27 { 28 my @mylist = @{$table{$username}}; 29 $m=0; 30 $totalsize=0; 31 $totaltime=0; 32 $gtotal=0; 33 $x=0; 34 $x=@mylist; 35 for ($m = 0 ; $m < ($x); $m++) 36 { 37 ( $seconds, $size, $file, $user, $group) = spl +it(' ', $mylist[$m]); 38 $totaltime = ($totaltime + $seconds); 39 $totalsize = ($totalsize + $size); 40 } 41 if ($totaltime==0) { $totaltime=1; } 42 if ($totalsize==0) { $totalsize=1; } 43 $avgtr = (($totalsize/$totaltime)/1024); 44 $gtotal=($totalsize+$gtotal); 45 $finale[$j]= join ' ', ($totalsize/(1024*1024)), $user +name, ($x), $totaltime, $avgtr; 46 # print $finale[$j]; 47 $j++; 48 } 49 @realfinal = sort @finale; 50 #print @finale; 51 $p=0; 52 $w=0; 53 $w=@realfinal; 54 #print $w; 55 for ($p=($w-1) ; $p>=0; $p--) 56 { 57 ($Size, $User, $Files, $Time, $AvgSpeed)= split " ", $ +realfinal[$p]; 58 $position= ($w-$p); 59 $percent=(($Size/($gtotal/(1024*1024)))*100); 60 printf ("$position. $User $Files files "); 61 printf("%.2fMB", $Size) ; 62 printf " $Time(s) "; 63 printf ("%.2f% ", $percent); 64 printf("%.2fK/s", $AvgSpeed); 65 print " "; 66 } 67

    Which, while blatantly stolen from here Qualifies as an ugly piece of code *i* have seen. You can also look at the other 2 articles in that series: here and here

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://163251]
Approved by particle
Front-paged by astaines
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2014-07-30 03:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (229 votes), past polls