dougo: (Default)
dougo ([personal profile] dougo) wrote2004-11-09 10:16 am

Postfix conditionals and language design

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?

Quoting from the perlstyle man page

[identity profile] daerr.livejournal.com 2004-11-10 02:04 pm (UTC)(link)
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.

Re: Quoting from the perlstyle man page

[identity profile] dougo.livejournal.com 2004-11-10 02:27 pm (UTC)(link)
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.

Re: Quoting from the perlstyle man page

[identity profile] novalis.livejournal.com 2004-11-10 05:07 pm (UTC)(link)
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)?

Re: Quoting from the perlstyle man page

[identity profile] dougo.livejournal.com 2004-11-10 05:40 pm (UTC)(link)
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.)

Re: Quoting from the perlstyle man page

[identity profile] novalis.livejournal.com 2004-11-10 08:08 pm (UTC)(link)
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.

Re: Quoting from the perlstyle man page

[identity profile] dougo.livejournal.com 2004-11-10 06:04 pm (UTC)(link)
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.