Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Confused by a couple of idioms

by nysus (Parson)
on Feb 21, 2019 at 22:07 UTC ( [id://1230334]=perlquestion: print w/replies, xml ) Need Help??

nysus has asked for the wisdom of the Perl Monks concerning the following question:

Being Perlmonk's most clueless Vicar, I continually find new idioms that leave me baffled. I'm looking though this code. On line 33, I see:

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

What is the slash doing there before my?

And on line 55:

$csv and $xls = $csv;

I've stared at this for a good 2 minutes and can't figure it out. I guess that's what keeps Perl so interesting. Thanks to the monks for your patience with me after all these years. :)

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Confused by a couple of idioms
by hippo (Bishop) on Feb 21, 2019 at 22:17 UTC
    $csv and $xls = $csv;

    Here and is used for control flow. It separates statements (or expressions) which are conditionally evaluated from left to right. The first is simply $csv and so the subsequent statement is only evaluated (and therefore executed) if this first expression is true. You can see then that the whole line is equivalent to writing

    $xls = $csv if $csv;
      Here this construction is equivalent, but variation with 'and' ends up as an expression and can be used further. E.g.,  print( $xls = $csv if $csv ); cause a syntax error, but with 'and' - don't.

      Also it is worth to mention that an alternative for "if( xxx ){ yyy }" one can use "xxx and do { yyy };" (with semicolon if it is the end of sentence; 'do BLOCK' in do docs)

        slight problem I see here (for me at least) is the use of && in *nix, in conditional execution, e.g. ls abc && grep aaa abc. You mentioned that && may not do what one intends. Do you have an example where && does not do what intended? thanks, bliako

      Ah, I was reading the precedence like this: ($csv and $xls) = $csv;

      I think the lowercase "and" basically makes it act more like this: $csv and ($xls = $csv)

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

        I think the lowercase "and" basically makes it act more like this: $csv and ($xls = $csv)

        Correct. Deparsing makes it even clearer:

        12:28 >perl -MO=Deparse -e "$csv and $xls = $csv;" $xls = $csv if $csv; -e syntax OK 12:29 >

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        I think the lowercase "and" basically makes it act more like this: $csv and ($xls = $csv)
        Yep. That's basically the entire reason that the and and or operators exist. and and or are low-precedence (making them useful for flow control), while && and || are high-precedence (making them useful for boolean logic). This is why, 99% of the time, open ... or die is correct and open ... || die is wrong.
Re: Confused by a couple of idioms
by jwkrahn (Abbot) on Feb 21, 2019 at 22:23 UTC

    "o|c|out=s" => \my $csv creates $csv at this point as a lexical variable and assigns a reference to it to (I assume) this hash value.

    $csv and $xls = $csv; tests if $csv is true, and if it is, assigns its value to $xls.

    It's the same as: $csv && ( $xls = $csv );.

      Here is the code in question in context; it is part of Getopt::Long

      use Getopt::Long qw( :config bundling noignorecase passthrough ); GetOptions ( "help|?" => sub { usage 0; }, "V|version" => sub { print "$cmd [$VERSION]\n"; exit 0; }, "man" => sub { exec "pod2man $0 | nroff -man"; }, "info" => sub { require Pod::Usage; Pod::Usage::pod2usage (VERBOSE => 2); exit; }, "o|c|out=s" => \my $csv, "i|s|in=s" => \my $xls, "f|force!" => \my $opt_f, "A|all!" => \my $opt_a, "N|no-pfx!" => \my $opt_N, ) or usage 1;

      It is assigning the value from the -o, -c, or --out switches to the $csv lexical variable that it is defining in-line

      Yeah, I just never knew you could put a backslash before "my." I've never seen that. Is that basically shortcut for:

      my $csv; %hash = { key => $csv };

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: Confused by a couple of idioms
by davido (Cardinal) on Feb 22, 2019 at 19:54 UTC

    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).


    Dave

Re: Confused by a couple of idioms
by nysus (Parson) on Feb 21, 2019 at 22:12 UTC

    PS, I know the backslash is probably a reference, but I've never seen it used before my like this. I just didn't think anything like this was syntactically possible.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      Dont be afraid of that. It's just a precedence issue, precedence of my operator is higher than reference op, no more other mysteries. You are maybe used to open (my $fh,....) it's the same.
        ... And a handy precedence list can be found in perlcheat.

        I have a question about precedence of my. Isn't it a 'named uop', as I thought, or is it absent from precedent list? E.g.
        perl -wle 'print( my $i ** 2 )' #Use of uninitialized value $i in exponentiation (**) at -e line 1. #0
        perl -wle 'print( my ( $i ** 2 ) )' #Can't declare exponentiation (**) in "my" at -e line 1, near ") ) #" #Execution of -e aborted due to compilation errors.
        It looks that precedence of 'my' is higher than usual 'named uops'.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1230334]
Front-paged by stevieb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (10)
As of 2024-04-16 08:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found