views:

227

answers:

6

I've seen perl statements that look like this:

() unless $some_var;

What is that intended to achieve?

A: 

if executes the statement once if and only if the condition is true.

unless is the opposite, it executes the statement unless the condition is true (i.e., if the condition is false).

see for more detail: http://perldoc.perl.org/perlsyn.html

() is merely the empty list, so this code is providing a default value of the empty list for cases where $some_var is false (probably because $some_var is undefined).

Nikhil Jain
Thank you, I understand the 'unless' part - but why the '()'? What does the empty list achieve?
Tony
A: 

It returns empty list if $some_var is false.

If I write @s = () unless $some_var;, I emptied @s if $some_var is false.

That is the only way this can be used I can think of.

Karel Bílek
Thanks - sorry if I wasn't clear, but this is all by itself on a line - no assignment.
Tony
+1  A: 

It's probably used in implicit return, if $some_var evaluates to true, return it, otherwise return empty list.

phadej
+1 only useful answer atm
Brian Rasmussen
Thanks - not sure how that can work, since it occurs at the start of a script, not in a subroutine, and the same script ends with an exit(0);
Tony
Keep in mind that when a subroutine exits the return value is the last value processed (or, if there is a `return` statement, whatever that `return` statement was called with).
PP
+1  A: 

On itself, this expression is a nop. But the value (empty list) can be automatically returned from a subroutine or do() block, if there's no explicit return statement and this value happens to be the last thing in the block.

eugene y
Thanks, I like this theory... but it is near the top of the main routine, a lot of stuff happens after it :-(
Tony
+8  A: 

There's a couple of things going on here, but most significant is the fact that this sort of line would usually appear as the last line of an executed block[1]. In that context, the value of the block is the value of the last executed statement[2]. Now a statement containing unless has the value of the left-hand side if the right-hand side is true and the value of the right-hand side otherwise, so this is a way of saying "the value of the block is $some_var if $some_var happens to be true, () otherwise".

() is merely the empty list, so this code is providing a default value of the empty list for cases where $some_var is false (probably because $some_var is undefined.)

It is more usual to achieve the same effect with or, as in the equivalent

$some_var or ();

Put together, we can see these cases:

use strict;
use warnings;

my @x = do { () unless 0 };
my @y = do { () unless 5 };

print "\@x: <@x>\n\@y: <@y>\n";

@x is the empty array because 0 is false, whereas @y is an array containing 5 because 5 is true.

Anywhere other than as the last statement of a block, () unless $some_var; is a no-op. It does suppress the once warning if $some_var is not otherwise mentioned, though.

[1]: That's a block evaluated by eval or do or supplied to (for example) map or grep, or a block called as a subroutine.

[2]: "The value of the last executed statement" is a weird phrase; mostly only expressions have values. But because Perl includes the concept that in the absence of an explicit return the value of a block is the value of the last statement, Perl needs this weird phrase.

darch
Thank you for the detailed analysis; doesn't seem to be what's happening here (if anything). Here's a bit more of a script, lots of subsequent code omitted, and it finally ends in an 'exit(0);' : #-- MAIN -----------------------------------------------------------------------GetOptions( "-interactive", "-request_file=s", )or usage();usage unless ($opt_request_file);() unless ($opt_interactive);$today = strftime ".%Y-%m-%d", localtime;$dte = strftime "%Y-%m-%d", localtime;@col = ("M","N","O","P","Q","R","S");. . .
Tony
Sorry if I formatted that badly, just cut and paste from putty, looked ok in this text box :-(
Tony
With that context, it looks like a no-op to me. At a guess, the interactive option is actually unimplemented cruft, and the unless statement is in there as a place holder for some code that never got written. I would not hesitate to remove it.
darch
Given the incorrect use of Getopt::Long displayed in that code sample, an alternative explanation becomes likely: The line is acting as as a way of suppressing a "used once" warning. Given that this compiles, I would advise adding "use strict" in addition to getting rid of the crufty option.
darch
This is really clever use of unless, albeit very obfuscated in my opinion. +1
Karel Bílek
Thank you, Karel, and thanks for wading through my unformatted code snippet!
Tony
Thank, darch - removing it doesn;t seem to cause any visible symptoms - trying to track down the author.
Tony
(Small correction: The usage of Getopt::Long is not actually wrong. It *is* useless, though. Mea culpa, should have checked rather than just skimming the docs.)
darch
And it's been my pleasure. Now to sleep before I make another misstatement on a public forum. =P
darch
+3  A: 

Mystery solved:

GetOptions(
    "-interactive",
    "-request_file=s",
) or usage();

usage unless ($opt_request_file);
() unless ($opt_interactive);

It seems the '();' is misleading - it does nothing, and the purpose is just to mention the $opt_interactive variable once... as a way to suppress the perl warning 'Name "$var" used only once'.

Thanks to all who tried to shed some light!

Tony