Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: Confused by a couple of idioms

by davido (Cardinal)
on Feb 22, 2019 at 19:54 UTC ( #1230415=note: print w/replies, xml ) Need Help??

in reply to Confused by a couple of idioms

This syntax:

"o|c|out=s" => \my $csv;

Is described in the docs for GetOpt::Long. It is part of a larger construct:

GetOptions ("length=i" => \$length, # numeric "file=s" => \$data, # string "verbose" => \$verbose) # flag

Of course any Perl subroutine that accepts parameters accepts them into @_ normally. So in this case we could envision sub GetOptions looking something like this:

sub GetOptions { my %options = @_; # ... }

Though it's not guaranteed to be like that. But at least the design of the GetOptions subroutine is to give the feel of key/value pairs. The key is a string that forms a mini-DSL for specifying option parsing semantics. And the value is intended to be a reference to a scalar into which the command line option's value is placed. As you can see in the example (taken from the SYNOPSIS section of the POD for GetOpt::Long we are supposed to pass scalar references to GetOptions.

my $sref = \my $scalar;

Is approximately the same as:

my $scalar; my $sref = \$scalar;

But in the case of the example you used, terseness is being given favor over simplicity. If you cut through the various layers, you end up with something like this:

my %hash = ( some_key => \my $value, # ... );

Which is shorthand for:

my $value; my %hash; $hash{some_key} = \$value;

And to alter the contents of $value you could do this:

${$hash{some_key}} = 'foo';

I hope that clears up at least that idiom. The next one isn't great. In fact, it's a little tricky and has to be used with caution. and is a very low precedence logical && short circuit. So instead of binding closely to $csv || $xls, it binds like this:

($csv) and ($xls = $csv);

Which is quite similar to:

$xls = $csv if $csv;

I wouldn't call this a great practice, though, because it forces one to think about the precedence table a little too much. Way too often I see this in code reviews:

sub foo { my $value = rand(5); return $value > 2 or die "Value was not greater than 2.\n"; }

We switched to or instead of and, but they are next to each other in the precedence table (and comes before or, but they're way lower than most other operators). What is wrong with this code? return binds more closely to $value > 2 than to or, so we will return before or gets a chance to cascade. It's more like this:

sub foo { my $value = rand(5); return($value > 2) or die; }

So in this case you'll always just get the boolean result of testing $value > 2 rather than ever cascading to the righthand side of the or.

On the other hand, this might work out better:

sub foo { my $value = rand(5); return $value > 2 || die; }

...though it may be a little confusing still, the semantics are like this:

sub foo { my $value = rand(5); return ( ($value > 2) || die ); }

... in which case the entire expression will be evaluated if $value is not greater than 2, so die will take place and return will not (unless, of course, $value IS greater than 2).


Log In?

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

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2019-08-22 02:28 GMT
Find Nodes?
    Voting Booth?

    No recent polls found