What I have found irritating about Perl is its TOTAL LACK OF READABILITY.... If you want proof, look at this:
my $msg = " spacey string "; $msg =~ s/^\s+//; $msg =~ s/\s+$//;
... I see a totally random series of symbols, as if a kid was writing something in 1337.
— Perl versus Python: The eternal battle
In a government course, I put together a phone survey where the querents asked people randomly selected from the phone book their opinion on made-up issues. We invented plausible but fictional decisions of the local government and pretended that they were true.
Thanks to the Internet, I no longer have to go to that much work to find ignorant opinions from people who've done no research. Also, English is impossible to read if you don't know the definition of the word "querent" in the previous paragraph. QED.
Just look at it:
msg = ' spacey string ';
msg.replace(r'^\s+', '');
msg.replace(r'\s+$', '');
That’s clearly orders of magnitude easier to read than the Perl version.
Re:You are an idiot
Aristotle on 2007-09-06T01:49:17
Oh wait, it has to be this:
msg = ' spacey string ';
msg = msg.replace(r'^\s+', '');
msg = msg.replace(r'\s+$', '');Or possibly chain the methods.
msg = ' spacey string ';
msg = msg.replace(r'^\s+', '').replace(r'\s+$', '');Perl can’t hold a candle to any of that.
Re:You are an idiot
pudge on 2007-09-06T02:17:34
Wow... I've seen many complaints about lack of readability, but this has to be the dumbest one (not yours, of course, the original). Just wow.
Re:You are an idiot
pudge on 2007-09-06T02:23:30
BTW, the "blogger" is apparently only 15, acc. to his profile. After reading the rest of his post I figured he was a dumb kid. So he is.
Sometimes I worry that the chorus of "Perl, in a Nutshell" will damage Perl's reputation ("it's so easy to write, but it's not always easy to read"). Then I think, if only I could be so lucky!
Re:You are an idiot
mr.bambers on 2007-09-06T04:07:20
As a new Perl programmer, and (I will disclaim now) having never written any PHP, I'd like to point out that no computer language has intrinsic "readability". Do you remember your first time ploughing through "Learning Perl"'s 'A Stroll Through Perl'?
No programming language is readable until someone invents a programming language that reads like a native language. Think Pseudo-code, and THAT is readable (or at least you'll get the idea...) However, no-one has made a REAL language like that. Yet.
I've been told by a Perl programmer that adding comments to Perl is "not the done thing" and is (apparently) unconventional. However, if there are comments it's readable. If there are none, it's difficult to read without having a good understanding and some patience.
If I post a piece of sheet music and you can't sight-read, would you find it readable? I can read music, but it takes me 30 minutes to translate a page. I can READ it, but it's not READABLE...
(Thank you for the chance to rant with my first post... I might be more constructive next time...:~);
Re:You are an idiot
pudge on 2007-09-06T04:32:40
I agree with much of what you say, but some quibbles:No programming language is readable until someone invents a programming language that reads like a native language.I don't accept that: I am fluent in Perl. It is nearly as a native language to me. I'd say no programming language -- or any language -- is readable to a person until they, simply, learn that language.I've been told by a Perl programmer that adding comments to Perl is "not the done thing" and is (apparently) unconventional. However, if there are comments it's readable. If there are none, it's difficult to read without having a good understanding and some patience.I wonder if perhaps you misunderstood slightly. I've never heard someone say that comments are not done if they are needed; the goal, however, is to make it so that your code is self-explanatory (to someone who knows Perl, of course). If I write this:that obviously needs no comment. However, this code, that produces the same output, is much harder to read, even for a Perl programmer:print "Perl";The latter needs comments, the former does not. And that's what many people mean when they say "don't comment": write code that doesn't need comments. Use variable and subroutine names and data structures and so on that are self-explanatory for Perl-speakers. And if it needs explanation, for you or someone else, either to know how the code works or what its purpose is, then by all means, comment!vec($str, 1, 32) = 0x5065726C;
print $str;
Re:You are an idiot
chromatic on 2007-09-06T04:56:37
No programming language is readable until someone invents a programming language that reads like a native language.I'm not sure that's even possible, at least for any interesting problems. It's not that interesting to discuss the abstract relative readability of programming languages; syntax is just one particular expression of the semantics of the solution to a problem. You have to understand the problem and the semantics of a problem as well, and once you start talking along those lines, you have to bring in the principle of the conservation of complexity.
Suddenly syntax isn't as abstract, or important. As Paul Hummer says, You simply cannot become an expert in Scheme by becoming an expert in its syntax. That's not where the power is.
You obviously have a lot to learn
btilly on 2007-09-06T12:06:58
I would suggest starting with Code Complete 2 to fill in the gaps.
After that you'll understand things like the inherent tradeoffs in commenting. It isn't as simple as "comments aren't done." And it isn't as simple as "comments make things readable." Instead it is much closer to, "comments are helpful but untrustworthy." Which is why there is a big emphasis on making your code (which can be trusted much more since errors there get noticed and fixed) read as much like comments as possible. (Much easier said than done!)
After you've come to understand principles like that, you'll be able to appreciate why pseudocode is not inherently more (or less) readable than a computer language, and making a computer language that reads like a native one does not suddenly make it easy to program. (The first language to try that approach was COBOL almost 50 years ago. There is a reason that modern computer languages are not marketed on the basis of being easy for your manager to read...) If you're lucky, you'll also be on your way to seeing how readability is an interaction between text and the reader, and how to use this to deliberately write code that is pitched to a specific type of reader.
And you'll be a better programmer. In any language you try to program in.Re:You obviously have a lot to learn
mr.bambers on 2007-09-06T19:17:00
I do have a lot to learn, and your comments and observations about this are most welcome. I'll check out Code Complete 2 (aaah... expensing is awesome) and will soldier on with the learning.
My original comments came from the fact I do black box testing at work, and have recently started to approach the source code. One way I find comments helpful is when they describe what the following function is supposed to do. If I just read through the function (slowly...:~) and figure it out I can see what it does. I can't tell if that's what it's supposed to be doing though, and I don't usually have a programmer there to ask.
Of course, given time I hope I'll find code as readable as you all. Right now it's a barely readable black box (to me) but wish me luck and I'll be around.
And thank you btilly, chromatic and pudge for your comments and direction!Re:You obviously have a lot to learn
btilly on 2007-09-06T21:35:15
One of my favorite comments on commenting is I find the most useful comments state what remains invariant, while the code states what gets transformed. (From this post.)
The explicit or implicit API presented by a function should not (lightly) be changed. Therefore it is often worthwhile to comment on that. And it is always worthwhile to pick a function name that tells you what it means. However the mechanics of how the function works internally should not generally be commented.
That said, there isn't any magic by which good programmers become magically able to find any code readable. You can probably improve quite a bit from where you are, but there are definite limits. For instance spaghetti is not particularly readable by anyone, and everyone gets slowed by it. Plus with any significant codebase, productivity strongly depends on how well you know your way around it. Being able to find what you want is partly a question of being able to read the code, and partly a question of being able to figure out what code to read. Memory plays a definite role in that process.
So even after you've learned to program well, you'll still have to accept that code will not always be easy for you to read.
That said, the value of good code is that good programmers can become extremely productive with it. They can understand it more easily, make changes faster, the changes are more likely to be correct, and there are fewer unexpected interactions between different parts of the code. Bad programmers also benefit from good code, but they just don't benefit as much, and their changes tend to reduce the quality of the code.Re:You obviously have a lot to learn
chromatic on 2007-09-07T06:27:32
Plus with any significant codebase, productivity strongly depends on how well you know your way around it.Also very important is your knowledge of the problem domain.
Re:You are an idiot
stvn_skuo on 2007-09-06T07:07:33
Perl can’t hold a candle to any of that.
But perl6 might...
http://xrl.us/ftqq
http://xrl.us/5obh
In Python that can be written as:
msg = msg.strip()
Re:You are an idiot
Aristotle on 2007-09-06T12:11:49
I expected that. Of course, until I read the documentation, I don’t actually have any idea about what
strip
does.Re:You are an idiot
sigzero on 2007-09-06T18:42:24
The Python version removes spaces from both sides of the text. Just create that in a sub{} in Perl and be done with it. : )Re:You are an idiot
Aristotle on 2007-09-06T18:56:32
I know. I’m saying that if I see
msg.strip()
in a random piece of Python code, and I’ve never seen the documentation ofstrip
, then I don’t know what it does, any more than I know what the Perl code does if I’ve never read the documentation.Re:You are an idiot
chromatic on 2007-09-06T19:54:36
You're absolutely right. I wish more people realized that.
Re:You are an idiot
ferreira on 2007-09-06T13:32:33
In Python that can be written as:Hey, but that's nearly impossible to write in Perl. Let me see:
msg = msg.strip()
# in-place version
sub strip { s/^\s+//; s/\s+$//; }
# which would be used as
strip($msg);Re:You are an idiot
Aristotle on 2007-09-06T14:49:30
That won’t quite work. Make it
sub strip { $_[0] =~ s/^\s+//; $_[0] =~ s/\s+$//; }or maybe
sub strip { s/^\s+//, s/\s+$// for $_[0] }Re:You are an idiot
sigzero on 2007-09-06T19:12:59
use strict;
use warnings;
my $string = " This is the test ";
sub trim {
my $a = $_[0];
$a = join(" ", split(" ", $a));
return $a;
}
my $nstring = trim($string);
print "$string\n";
print "$nstring\n";
I don't think it takes every case...but it works with the "test" string.Re:You are an idiot
btilly on 2007-09-06T21:43:14
The latter version can be generalized to:sub strip { s/^\s+//, s/\s+$// for @_ }
However I don't like the idea of modifying arguments in place. Functions that do that violate my expectations. Instead I'd make a copy and return the copy. Like this:sub strip {
return map strip($_), @_ unless 1 == @_;
my $x = shift;
$x =~ s/^\s+//;
$x =~ s/\s+$//;
return $x;
}Re:You are an idiot
Aristotle on 2007-09-06T21:53:00
The latter took me a while to read. I’m not used to recursion so casually… and it seems to me that deliberately creating opportunities to get the termination condition wrong is an unnecessary source of bugs.
I agree though that returning a copy is better; I wrote my code that way only because was correcting the example code.
Personally I’d write it like this:
sub strip {
my @stripped = @_;
s/^\s+//, s/\s+$// for @stripped;
return @stripped;
}On a related tangent, I’ve often wished for a variant of
s///
that modifies a copy of the string and returns that.Re:You are an idiot
btilly on 2007-09-06T22:22:43
There is a subtle but significant difference between the two versions that shows up if someone writesmy $bar = strip($foo);
Your code will return 1 in that case, while mine returns $foo stripped appropriately.To fix that you would need to check wantarray. Or you could return
@_[0..$#_]
instead.Personally I have a lot of utility functions that usually accept one value, but sometimes accepts a list and returns a list. I find it annoying to add the loop and the wantarray check to each one. And I find that I always am passing in only one value when I want to return one value. It is not quite as good if you're paranoid, but the assumption works for me. So for me
return map function($_), @_ unless 1 == @_;
has become an idiom. I just stick that in, then write the case for a single argument. At a glance I know that it will handle one argument or many, and the logic of what it does is not obscured by the mechanics of the loop.Re:You are an idiot
Aristotle on 2007-09-06T23:30:33
I see the points, but I still don’t like the idiom. It has several moving parts that have to be arranged just so, and you have to read carefully to trace its self-interaction to understand what is really going on.
I prefer to write simpleton code. I also prefer to avoid conditionals for the same reason, so I’d use
@_[0..$#_]
overwantarray
. All told, for a general-case idiom I’d settle on this:sub foo {
for ( @_ = @_ ) {
#...
# mutate the iterator here
#...
}
return @_[ 0.. $#_ ];
}This is straight code, IMO. There is very little going on here on a conceptual level. I wouldn’t have any trouble with reading this, nor with re-deriving it on the spot. (As a fringe benefit, this structure is more efficient too – a correlation that seems frequent. But I’ll pick dumb over efficient by default in those cases where they are in antagonism.)
I don’t think the loop really gets in the way there, other than increasing the indentation level once.
Re:You are an idiot
runrig on 2007-09-07T00:07:54
I'm too dumb to remember what the difference between@_
and@_[0..$#_]
is (and I'd guess others are also), so MHO is that wantarray would be preferable. I like btilly's way also, though it does make more function calls when run on a list. And on a side note, I also find the title of this thread amusing:-) Re:You are an idiot
btilly on 2007-09-07T02:57:17
A lot of this is personal taste. All solutions are ugly. Yours involves an extra level of indentation, assignment in the for loop declaration (normally a red flag), and the subtle return construct.
I'll note that efficiency depends on your use case. My approach is more efficient for the single argument case. Yours is more efficient for the list case. (More efficient than either of our versions is to make your return depend on a call to wantarray.)
Anyways there was a period where I had to write a bunch of these. And adding one line per just worked out to be easier for me than adding several lines and adding another layer of indentation.Re:You are an idiot
Aristotle on 2007-09-07T03:22:50
Well, I’ve actually written a module to deal with that sort of thing, so…
my $msg = " spacey string ";
$msg =~ s/^\s+//;
$msg =~ s/\s+$//;
Re:It's gone
chromatic on 2007-09-07T06:25:39
His entire blog is now gone.Whoa. I took a 15 year old off of the Internet. I'm sort of proud and sort of not.
Re:It's gone
petdance on 2007-09-07T06:36:46
I posted a more welcoming comment, posting equivalent code in C and pointing out that the Perl code was much easier to read, once you understood it, and that brain cycles were better spent working on the programming problem than the specifics of how to remove spaces from a string. I invited him to look into Perl some more before writing it off.
I was hoping it might do some good.
It's easy to quibble about readability with trivivial examples. But a "readable" language often implies "limited in power" too. So how would you solve the same problem with the added requirement that multiple spaces should be squashed into a single space? In Perl it's easy: you just have to add the additional statement:" a spacey string "
ortr///s;
(Too bads/\s+//g;
tr
doesn't recognize the \s
meta character class.)
So how do you tackle that in a readable language like Python? I don't know enough Python, let's stick to something I do know: PL/SQL, the (Ada-based) language Oracle includes in its databases:
That's what "readability" buys you: a requirement for a lot of extra, very low level code. But, it least it's "readable"!function normalize_spaces(s in varchar2) return varchar2 is
r varchar2(32000);
begin
r:= trim(s);
while(instr(r, ' ') > 0) loop
r:= replace(r, ' ', ' ');
end loop;
return r;
end;
I wouldn't be too surprised that in general, Python makes you jump through the same hoops, as Guido is notorious for ripping out features out of the language he considers too advanced.
p.s. I like Javascript, and their solution really appeals to me:
I really like chaining in this way. Much better than the nesting of procedural function calls that you have to write backwards — the last function to call is the first one you read in the source. And Javascript knows first class regular expressions (which are like qr// objects in Perl).function normalize_space(s) {
return s.replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g, ' ');
}