Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

(Ovid - accidental obfuscation?)Re: Perverse Unreadable Code

by Ovid (Cardinal)
on Apr 25, 2001 at 23:17 UTC ( [id://75571]=note: print w/replies, xml ) Need Help??


in reply to Perverse Unreadable Code

I strongly sympathize with your point of view. There are clearly those out there who write code that is not meant to be read. On the other hand, sometimes unreadable is churned out as a matter of course. From a program I'm currently writing:
%author = map { /^\d{6}$/ ? $_ : [ split( /\|/, $_, 2 ) ] } map { split( /=/, $_, 2 ) } grep { /^\d{6}=[^|]+\|/ } <FH>;
Frankly, I can't say that I'm happy with the illegibility that this code presents to the average programmer. Heck, a few months ago, I wouldn't even have been able to read it. Now, however, I sat down and simply wrote it out. There was only one bug (forgetting the third argument to split) and it worked fine.

While I'll need to stop and read through that when I come across that again, it really seems to be the most straightforward "Perlish" way of writing that. Further, once one develops a high comfort level with Perl, such constructs become (dare I say?) natural.

Much of the trouble that people have with such things stems from the large amounts of punctuation. This has the unfortunate side-effect of steepening Perl's learning curve. Your patience in learning such things, though, will reward you handsomely in the long run as your ability to harness the full power of Perl develops.

Side note: do any monks use English for any production code? I've heard about the module and see how it makes Perl more legible, but I've never seen anyone actually use it.

Cheers,
Ovid

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

Replies are listed 'Best First'.
Re: (Ovid - accidental obfuscation?)Re: Perverse Unreadable Code
by btrott (Parson) on Apr 26, 2001 at 02:00 UTC
    Re: your code--I think that were I presented with the same problem I'd probably do it like this:
    my %author; while (<FH>) { next unless /^\d{6}=[^|]+\|/; my($l, $r) = split /=/, $_, 2; $author{$l} = [ split /\|/, $r, 2 ]; }
    I don't like temporary variables much, either, but this, to me, seems:
    • more readable
    • more efficient, both in terms of memory and "algorithm". Your code loops over the data three times (I think); the above would loop over it only once. Furthermore, your code loads the entire contents of FH into memory at the same time, while the above processes the file line by line.
    I'm not trying to bash you or anything. :) Readability is often a rather subjective thing, for one thing, and if you find your code more readable, that's fine.

    In terms of efficiency, though, I think the while loop probably beats a grep-map-map operation (read in reverse), unless there are other issues I'm not thinking about.

      This is a beautiful example of how we can mentally get into a rut and not "rethink" things. Your code is much easier to understand. Thanks!

      Cheers,
      Ovid

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

      Funny, I was thinking virtually the same thing myself looking at his code, but more along the lines of:
      my %author; while (<FH>) { next unless /^(\d{6})=([^|]+?)\|(.*)/; $author{$1} = [ $2, $3 ]; }
      Though perhaps I've missed something here.
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
use English (was: Re: (Ovid - accidental obfuscation?)Re: Perverse Unreadable Code)
by KM (Priest) on Apr 26, 2001 at 00:06 UTC
    do any monks use English for any production code?

    I don't even use it for test code :) It can make a script slower, especially if you are using regular expressions.
    Right from the POD:

    =head1 BUGS This module provokes sizeable inefficiencies for regular expressions, due to unfortunate implementation details. If performance matters, consider avoiding English.

    This is mainly (the RE part) because it brings $& $' and $` into the game.

    Cheers,
    KM

Re: (Ovid - accidental obfuscation?)Re: Perverse Unreadable Code
by tinman (Curate) on Apr 25, 2001 at 23:45 UTC

    As mentioned in a /msg, I've seen some examples for XML::Parser that use it..You can find the link here... I think none of the examples for the current XML::Parser version use it though..

    Perhaps out of context, and it may have changed later, but this is a thread I found through Google on use English in Perl 6... Link to message archive is here..

    I've wanted to use English in the stuff I write, but I have enough trouble remembering magic variables as it is... so, doesn't look like it's going to happen anytime soon.. :o)

Re: (Ovid - accidental obfuscation?)Re: Perverse Unreadable Code
by dws (Chancellor) on Apr 25, 2001 at 23:23 UTC
    Side note: do any monks use English for any production code?

    Yes, but not religiously. We use it for some of the lesser-used variables, such as saying $INPUT_RECORD_SEPARATOR instead of $/. But we still use $_ instead of $ARG.

      No, never. If I had to go through the trouble of learning all those arcane variables, why shouldn't everyone else?

      </HUMOR>
Re: (Ovid - accidental obfuscation?)Re: Perverse Unreadable Code
by runrig (Abbot) on Apr 26, 2001 at 21:33 UTC
    I suspect the redundancy and memory requirements in your one-liner is inefficient and that a while loop would be not only more efficient but more readable. Benchmark in progress ...

    Update:After reviewing the original, its not exactly the same, but I think still a fair enough comparision :)

    #!/usr/bin/perl -w # About the fairest comparison I could think of at the moment use strict; use Benchmark; my $file = "tst1.txt"; open(OUT, ">$file") or die "Can't open $file for output: $!"; for ("000000".."020000") { print OUT "$_=abc|def|ghi|jkl\n"; print OUT "Ignore this line\n"; } open(FH1, $file) or die "1 Can't open $file: $!"; open(FH2, $file) or die "2 Can't open $file: $!"; timethese(1, { MAPIT=>\&map_it, LOOPIT=>\&loop_it, }); close FH1; close FH2; sub map_it { my %author = map {/^\d{6}$/ ? $_ : [ split (/\|/, $_, 2 ]} map { split( /=/, $_, 2 ) } grep { /^\d{6}=[^|]+\|/ } <FH1>; } sub loop_it { my %author; while (<FH2>) { next unless /^(\d{6})=(.+)\|/; # Hmm, the above should really be: # next unless /^(\d{6})=([^|].*)\|/; # Whoops, forgot to limit the split to 2 elements here # No big deal, results are still similar $author{$1} = [ split(/\|/, $2) ]; } } # interesting different results #Under activestate perl Benchmark: timing 1 iterations of LOOPIT, MAPIT... LOOPIT: 5 wallclock secs ( 4.62 usr + 0.00 sys = 4.62 CPU) @ 0 +.22/s (n= ) (warning: too few iterations for a reliable count) MAPIT: 28 wallclock secs (28.73 usr + 0.00 sys = 28.73 CPU) @ 0 +.03/s (n= ) (warning: too few iterations for a reliable count) #under Cygwin perl $ ./tst Benchmark: timing 1 iterations of LOOPIT, MAPIT... LOOPIT: 4 wallclock secs ( 4.67 usr + 0.00 sys = 4.67 CPU) @ 0 +.21/s (n= ) (warning: too few iterations for a reliable count) MAPIT: 5 wallclock secs ( 5.22 usr + 0.00 sys = 5.22 CPU) @ 0 +.19/s (n= ) (warning: too few iterations for a reliable count)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://75571]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2024-03-28 22:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found