So I'm reading some Perl code. I usually stay away from Perl as much as I can, but I'm trying to figure out some undocumented behavior of the MusicBrainz RDF server so I have to UTSL. Anyway, I get to this line:
      return ("No artist name or artist id given.", $data, 0, undef) 
and I get confused, because I saw the artist ID check but not the artist name check. So I start reading backwards to see if I missed something; maybe the artist name check happened in some non-obvious function call? I go skimming through various other files to see if some other code is filling in the artist ID or something. Eventually, I give up and come back to that line, and I notice that the next line is:
          if ($data->{artist} eq '');
and I smack my head. I'm willing to chalk this up to bad style (and I hope people would agree this is bad style), but now I'm wondering: when is it ever good style to put the conditional guard after the code it's guarding? Or, more generally, when is it ever good style for the order of code (in the same basic block) to be the opposite of the order of execution?

From: [identity profile] petdance.livejournal.com


On long things like that, I don't use the post-condition. But there are plenty of cases where it does make sense:
next if /^\s*#/;  # Skip comment lines

return 1 if $already_checked;

return unless $DEBUG;

warn "Invalid stooge" unless $stooge =~ /^(Moe|Larry|Curly|Iggy)$/;
The common metaphor of
open( my $fh, $filename ) or die "Can't open $filename: $!\n";
is just a post condition version of
if ( !open( my $fh, $filename ) ) {
    die "Can't open $filename: $!\n";
}

From: [identity profile] dougo.livejournal.com


The first four examples seem more like specialized conditionals than compound statements. I.e. "next if" could almost be considered syntax itself.

I don't get the last example, though. Wouldn't the post condition version be:
  die "Can't open $filename: $!\n" unless open(my $fh, $filename);

From: [identity profile] bitjuggler.livejournal.com


'or' is is a boolean shortcircuit operator and not really a postcondition, though the shorcircuit part makes it work like one, just like 'and' can work as an 'if' statement:

(!open(my $fh, $filename)) and die "Can't open $filename: $!\n";

Switching back to the main topic of conversation, the one thing in Python I occassionally really really want is a 'repeat..until' loop for cases where I want some code executed at least once but likely more.

From: [identity profile] petdance.livejournal.com


Sure, you can also say
die ..... unless $something

but I really don't like that in most cases.


Basically, I put the most important part first in any long construct. In the case of the open(), that's what's really key. Think of it in English. Are you saying "Unless it's raining, we'll have a picnic", or do you say "We'll have a picnic, unless it's raining." The picnic is usually the most important part.


From: [identity profile] dougo.livejournal.com


Right, but I wouldn't say "We'll have a picnic, so I need you to make some potato salad, and leave out the onions... unless it's raining."

From: [identity profile] mshonle.livejournal.com


It's sad that "language designers" of the languages used today don't know much about language design. They (like Larry Wall and Guido Van Rossum) focus only on syntax, so they come up with dumb, experimental ideas of little importance (like that stupid, stupid tab crap in Python; and all of that conditional stuff in Perl). Moreover, these hacks completely miss "the good stuff" like lexically scoped closures (and not until many version later, likely from Scheme people demanding enough that they put in weak versions).

Python is particularly curious; from the get-go it had "lambda" but it was so horribly weak it was obvious the designer didn't even understand the languages he was so blantantly copying from. (I believe he copied from Ruby, which got closures in the Scheme sense right; which Ruby copied from Smalltalk).

At OOPSLA, the creator of Smalltalk, Alan Kay, said "My language represents an improvement, particularly among its successors". (He was quoting what was originally attributed to the creator of Algol.)

Alas, people like you and I who know better (i.e., know Scheme) are stuck with languages like Perl sometimes or Python/Zope. Meanwhile, the wonderfully designed languages like Dylan have no user base or libraries. I'd probably do a lot more web-programming if Dylan were somehow the language of choice for it.

From: [identity profile] mshonle.livejournal.com


Can you give me the gist of it? Hopefully it's more than just "hackers get things done, instead of painters who make beautiful things that are useless." I've already granted that Perl and Python are useful; it's just that there are so many missed opportunities in both languages that it's a tremendous pitty.

Anyway, it's just a fact that sometimes the trivial dominates over the fundamental. I used to be the same way until I studied programming languages at Northeastern under Mitch Wand, Matthias Felliesen, and Karl Leiberherr.

From: [identity profile] dougo.livejournal.com


It's written by Paul Graham, so I think he's on our side. For example, in a talk he gave at Northeastern:
If I could get people to remember just one quote about programming, it would be the one at the beginning of Structure and Interpretation of Computer Programs.
Programs should be written for people to read, and only incidentally for machines to execute.

From: [identity profile] bitjuggler.livejournal.com

Exactly...


syntax is for people, so denigrating language designers who focus on syntax and 'dumb, experimental ideas of little importance' seems to me to be denigrating what I see as the main object of language design: to make programs easy to understand for both the writer and future readers (and incidentally for the machine itself).

From: [identity profile] dougo.livejournal.com


I'm pretty sure Python pre-dates Ruby, but I'm too lazy to check.

From: [identity profile] prusik.livejournal.com


Without stating an opinion one way or the other about how much Guido knows about language design or whether he was focussed only on syntax, I have to point out that languages with impeccable pedigree like Miranda and Haskell implement the off-side rule. (Miranda dates to the mid-80s so that predates Python by about 5 years.) I've never used Miranda but I have to say that using indention to control scope works surprisingly well in Haskell. However, for some reason, I find it annoying in Python. Perhaps it's because functions tend to be rather short in Haskell. (That and, yes, Python needs a real lamdba.)

As for the perl fragment in question, the camel book actually talks about when it's good style or not. However, it's at work and I'm at home. I think it's something like "put the important clause first"

As for my weapon of choice, when I'm not being paid, it's almost surely Ocaml. It's mostly functional, has a powerful, terse syntax and has a really good native code compiler.

From: [identity profile] jfb.livejournal.com


When is it ever good style to write perl?

From: [identity profile] novalis.livejournal.com


It probbably was originally shorter, such that it fit on one line. Then it would be better style (as noted in [livejournal.com profile] petdance's comment).
(deleted comment)

From: [identity profile] novalis.livejournal.com


I guess I have to disagree with this -- "next if" and "return if" give a net savings of two lines, and while brevity shouldn't be chosen at the expense of clarity, it's generally a good thing. If you're editing code, you have the responsibility to make it clean, just as you do when you're writing it.

From: [identity profile] dougo.livejournal.com


It's only two lines if you use two lines—or does Perl enforce line breaks or something?

From: [identity profile] novalis.livejournal.com


No, it's only two lines if you put in a line break. But otherwise, at least with indent, it's so long that it wraps.

From: [identity profile] dougo.livejournal.com


I was actually thinking about amending the basic-block thing after I posted, but I figured no one would care. :) What I meant was expressions in the same "leaf" procedure, i.e. not in different procedures that happen to be inside the same procedure.

From: [identity profile] daerr.livejournal.com

Quoting from the perlstyle man page


Just because you CAN do something a particular way doesn't mean that you SHOULD do it that way. Perl is designed to give you several ways to do anything, so consider picking the most readable one. For instance

open(FOO,$foo) || die "Can't open $foo: $!";

is better than

die "Can't open $foo: $!" unless open(FOO,$foo);

because the second way hides the main point of the statement in a modifier. On the other hand

print "Starting analysis\n" if $verbose;

is better than

$verbose && print "Starting analysis\n";

because the main point isn't whether the user typed -v or not.


From: [identity profile] dougo.livejournal.com

Re: Quoting from the perlstyle man page


I don't really buy that logic. Just because it's the main point doesn't mean it should go first. I still think sequentiality is more important. If the condition is so long that it distracts from reading the flow of the algorithm, it should be abstracted into a function.

From: [identity profile] novalis.livejournal.com

Re: Quoting from the perlstyle man page


But there's plenty of non-sequentiality in real code -- consider f (g (x)). g(x) is executed first, even though it's written after f. Do you recommend y = g (x); f (y)?

From: [identity profile] dougo.livejournal.com

Re: Quoting from the perlstyle man page


I should have been more careful with my terminology: I'm talking about evaluation order, not execution order. In the expression "f(g(x))", the procedure named "g" is executed before the procedure named "f", but the expression "g" may or may not be evaluated before the expression "f". (Scheme doesn't specify evaluation order for an application expression; I don't know if Perl does. Actually I don't even know if an operator in Perl can be an expression or must be a name.)

From: [identity profile] novalis.livejournal.com

Re: Quoting from the perlstyle man page


I don't know if it's defined, but my random test showed perl evaluating the arguments to a function before it evaluates the name of the function (and by name, I mean "expression returning code ref, whatever that may be").

Python is the other way around.

From: [identity profile] dougo.livejournal.com

Re: Quoting from the perlstyle man page


Thinking more about this, maybe what's really bothering me is that Perl post-conditionals are both non-sequential and infix. I think I wouldn't mind so much if it had prefix syntax:
post-if return ("No artist name or artist id given.", $data, 0, undef)
        ($data->{artist} eq '');
Hm, maybe that's still a bad idea. Nevermind.
.