Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

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

by anaconda_wly (Scribe)
on Sep 05, 2013 at 02:33 UTC ( #1052471=perlquestion: print w/ replies, xml ) Need Help??
anaconda_wly has asked for the wisdom of the Perl Monks concerning the following question:

I'm reading HTTP::headers code. I understand what GET mean, when only one argument, @_ becomes empty and $op will choose GET. But I can't understand PUSH and SET logic before the 2nd "?". Before receiving any value, $seen{field_name} must be empty, so what does $seen{field_name}++ mean? What's difference of PUSH and SET?

Another question is if wantarray line. I read http://perldoc.perl.org/functions/wantarray.html but didn't understand."if the context of the currently executing subroutine or eval is looking for a list value". What "the context" refers here, @old returned by $self->_header?

sub header { my $self = shift; Carp::croak('Usage: $h->header($field, ...)') unless @_; my(@old); my %seen; while (@_) { my $field = shift; my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET'; @old = $self->_header($field, shift, $op); } return @old if wantarray; return $old[0] if @old <= 1; join(", ", @old); }

I delete the line about "++" to state more clear about my question.

Comment on What's this line means in HTTP::headers?
Download Code
Replies are listed 'Best First'.
Re: What's this line means in HTTP::headers?
by kcott (Abbot) on Sep 05, 2013 at 03:50 UTC

    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

      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

Re: What's this line means in HTTP::headers?
by Anonymous Monk on Sep 05, 2013 at 02:42 UTC
Re: What's this line means in HTTP::headers? ("the context")
by Anonymous Monk on Sep 05, 2013 at 02:49 UTC

      Also I know the context meaning in some cases saying

      my $var = @array

      But here in specific case:

      return @old if wantarray;
      Does that mean if wantarray is always true? since @old is always an array?
        No. wantarray has nothing to do with @old, it has to do with how sub header is called, in what context.
      Yes, I know Auto-increment sign but just didn't understand the outcome here.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1052471]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (11)
As of 2015-07-31 05:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (274 votes), past polls