Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: What's this line means in HTTP::headers?

by kcott (Archbishop)
on Sep 05, 2013 at 03:50 UTC ( [id://1052482]=note: print w/replies, xml ) Need Help??


in reply to What's this line means in HTTP::headers?

G'day anaconda_wly,

Here's a breakdown of what's happening with:

my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET';

You've got a nested ternary operator here. Firstly, looking at the outer ternary. You've said you understand that when @_ is empty (i.e. FALSE), $op is assigned 'GET'. So, if @_ is not empty (i.e. TRUE), $op is assigned whatever ($seen{lc($field)}++ ? 'PUSH' : 'SET') evaluates to.

"($seen{lc($field)}++ ? 'PUSH' : 'SET')" is the nested ternary. If ($seen{lc($field)}++ is TRUE, 'PUSH' will be assigned to $op; if it's FALSE, then 'SET' will be assigned to $op.

"$seen{lc($field)}++" uses the postfix increment operator. This means that the value is returned first; afterwards the increment is performed. If the '++' was at the front (the prefix increment operator), the increment would be performed first and the incremented value would be returned. A simple code example might explain this better:

$ perl -Mstrict -Mwarnings -le ' my $x = 1; print $x++; print $x; my $y = 2; print ++$y; ' 1 2 3

$x starts as 1; $x++ evaluates to 1 for its print statement; afterwards, it's incremented to 2 as print $x shows. $y starts as 2; ++$y evaluates to 3 for its print statement, i.e. the increment is done first.

Back to "$seen{lc($field)}++". If %seen doesn't have a key lc($field), then $seen{lc($field)} will evaluate to FALSE (i.e. $op = 'PUSH'); after that evaluation, $seen{lc($field)} is incremented with the key being created (that's called autovivification) and the value being set at 1 (FALSE in numeric context is zero; 0 + 1 = 1). If %seen does have a key lc($field), its value will be at least 1 and $seen{lc($field)} will evaluate to TRUE (i.e. $op = 'SET'); $seen{lc($field)} will then be incremented again.

Using a hash called %seen (or similar name) and autovivifying keys (with a postfix increment) as they are seen is a common idiom. It would be worth your while studying this closely and ensuring you fully understand everything that's going on here: it's something you're likely to see often.

For wantarray, the context is the calling context; it's got nothing to do with the context inside the executing subroutine. The following may suffice to explain this:

my @return_values = function(@args); # wantarray TRUE my $return_value = function(@args); # wantarray FALSE

-- Ken

Replies are listed 'Best First'.
Re^2: What's this line means in HTTP::headers?
by anaconda_wly (Scribe) on Sep 05, 2013 at 06:49 UTC

    Thank you Ken. For wantarray, it's exactly answer what I want. I also tried a test.pl verify it. I understand PUSH and SET after reading your comments. My another question is about the reason of using the ++. If the 0(false) is added to 1, what's the incrementing for? It's not like an iterator's or a pointer's moving we normally see. The increasing didn't change anything seemingly.

    For "++" sign in Perl, I only use it in some simple cases and seldom embedded it into a complicated expression. In some language, "++"'s action is dependent on the compiler's implementation and I should know the language very well or may easily make error. When I saw "$seen{lc($field)}++", I'm thinking which operator wll take the highest priority to interpreter, "($seen{lc($field)})++" or "$seen({lc($field)}++)". I decided to find some artical about Perl Ops priority to read first.

      "My another question is about the reason of using the ++. If the 0(false) is added to 1, what's the incrementing for? It's not like an iterator's or a pointer's moving we normally see. The increasing didn't change anything seemingly."

      I don't understand what point you're making here. Take a look at these two scripts: the first with ++, the second without.

      $ perl -Mstrict -Mwarnings -le ' my @fields = qw{a a b c b a}; my %seen; for my $field (@fields) { print $field, $seen{$field}++ ? "PUSH" : "SET"; } ' aSET aPUSH bSET cSET bPUSH aPUSH
      $ perl -Mstrict -Mwarnings -le ' my @fields = qw{a a b c b a}; my %seen; for my $field (@fields) { print $field, $seen{$field} ? "PUSH" : "SET"; } ' aSET aSET bSET cSET bSET aSET

      That may clarify whatever is causing confusion or misunderstanding. If not, please supply a similarly short piece of code to explain your point.

      "... I decided to find some artical about Perl Ops priority to read first."

      Take a look at "perlop - Perl operators and precedence". There's a table of precedence and associativity at the start of the documentation. While you're there, you might as well also look at these sections further down the page: "Auto-increment and Auto-decrement" for "++" and Conditional Operator for "?:".

      -- Ken

        Thanks. My head must had been frozened. Your example is very helpful and interested. $seen only make a tag to what have seen in the @_, for some fields might be repeated in the @_.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (7)
As of 2024-03-19 08:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found